R for Dummies (BIOL208 Edition)
Welcome to this R tutorial for BIOL208! This is designed for someone who is brand new to R, so we are going to start with the very basics. To make this interesting, we’ll be looking at a dataset on irises since plants are extremely important to the study of ecology and evolution. To best follow along, you should have a new markdown file open in R studio where you can copy and paste line sof code from this tutorial for you to practice running on your own.
Typically, when doing data analysis in R, we want to begin by loading in the data and packages that we will use.
Loading Libraries and Data
R has many built in functions that will allow us to perform all kinds of actions. However, sometimes it is useful to load some additional functions that other R users have created. We do this by loading in libraries. In the code chunk below (the grey box; this is where code is typed and run) you can see that I have loaded in some libraries.
# Load other packages here.
#I just put in any libraries we might need. Don't know if we actually need them, or need more.
if (!require("tidyverse")) install.packages("tidyverse"); library(tidyverse)
if (!require("cowplot")) install.packages("cowplot"); library(cowplot)
if (!require("UsingR")) install.packages("UsingR"); library(UsingR)
if (!require("ggpubr")) install.packages("ggpubr"); library(ggpubr)
if (!require("readxl")) install.packages("readxl"); library(readxl)
Libraries
For some examples, one library is called tidyverse. It contains a ton of useful tools, but the one most relevant to this tutorial is called ggplot. ggplot allows us to create all kinds of plots to visualize our data, which you will learn more about below. You can also see the library called cowplot. cowplot is useful as it allows us to easily change the aesthetics of our graphs, and keep the designs consistent between different graphs. Finally, you can see the library readxl. This is useful for exactly what it sounds like… reading Microsoft Excel files! This bring us to the next step, entering data into R.
Data
In the code chunk below I am going to read in some data regarding features of different species of iris (the flower). There are a few main parts of the code to think about when loading in data. First, the read_csv() function tells R to load in a comma separated values (csv) file with the name of the file in the parentheses. Here, you can see that our data is called “iris.csv”. It is very important to type the file name exactly as it is saved on your computer, otherwise R will not be able to find it. Once the data is loaded in, we need to call it something. That is what the “IrisData <-” part of the code means. In English, it translates to: IrisData is the data found in the csv file “iris.csv”. When you read in a data file, you will see it appear in your “Environment” on the right of R studio. If you click on “IrisData” in your Environment, a new tab will appear with all of the data.
IrisData <- read_csv ("iris.csv")
Rows: 150 Columns: 5
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): variety
dbl (4): sepal.length, sepal.width, petal.length, petal.width
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
What happens if your data is in an excel file instead of a csv file? Fear not! Data can also be loaded in from an excel file using the read_excel() function instead of read_csv(). In a normal data analysis, you would only read in the data once using either the read_csv() or read_excel() functions. Your data will only read in properly if the file type matches the function you’re using, so pay attention to how your data is saved before you read it in!
Using R (The Basics)
Now that we have the pieces we need, we can start learning about R. You have already seen a few aspects of R in the last section, but here we will go into some more detail about the basic functions of R to get you started with analyzing data.
This document is an R markdown file. The highlights of a markdown file is that you can have mostly regular text (not code) but still include code and their output in specific sections. This is especially useful as it allows for lots of explanation of what the code does, like we need to do here for a tutorial. Markdowns are also convenient because they can be converted to many different formats such as a PDF (like you’re reading), an html, and others.
As mentioned before, the grey sections are called code chunks. This is where the actual code is written and ran. You can insert a code chunk to your markdown file by clicking the green box with “+C” at the top of R studio. When you do this, a drop-down menu appears where you can choose a coding language (since this is about R, we will only use that). Refer to Figure 1 if you can’t find the code chunk button.
In the top line of your new code chunk, you’ll see ```{r}. This can be used to name your code chunks if you wish. This can help keep your thoughts organized and is actually an important part of knitting your file…Say what??? We’re going to be knitting? Don’t worry, we’ll explain all the details about knitting in the later sections of this tutorial. For now just know that naming your code chunks can help organize your thoughts and can save you problems with knitting later down the road if you make sure to name your each of your code chunks something unique.
#Example code chunk
4+1
[1] 5
#This line will not run
Code within chunks can be run in a few ways:
- In the top right of a chunk is a green play button that will run every line of code in the chunk.
- Placing your cursor on a line you want to run, or highlight it, and hit command + enter (or control + enter).
- Click the run button in the top of the screen, which will bring up a few options for running code. You can run all of the code chunks in your document at once (in order from top to bottom) with this option. This is useful for ensuring your code is functional when finalizing a document.
Figure 2 outlines where you can find each of these.
Looking at the example code chunk above, there a few points to make about coding in R. First, you can see a green line that starts with a “#”. The hashtag/number/pound symbol tells R that this line is a comment, and that it should not be run as code. If you run the code chunk you will see that that line is skipped, and the only output comes from the addition found in the next line (the output should be 5 since 4+1=5). Comments are very useful for explaining your code as you write it. This is helpful for yourself in the future, so you can remind yourself how different code works, and for other people reading through or referencing your code.
Another useful bit of information is how to assign values to objects. Essentially, this is a way of naming things. You have actually already seen this in action, where we assigned our iris data to the object IrisData using the assign operator <-. Lets go to the next code chunk to see an example and notice how all of these values/variables will get stored in the Environment.
#Essentially, the <- means "store this value under this name," so you can think of the symbol as the word "is" or "equals."
this <- "that"
#In the line above we are storing the word that under the name this. So the code would read in English "this is that". And if we print out the object (a.k.a. run the code) "this," it will output the word "that." Try this out yourself! In your markdown file, try running the next line, but be sure to run the line above first.
this
[1] "that"
#Other examples
n <- 5
z <- 10
n+z
[1] 15
z/n
[1] 2
(z+n)/3 -> five
five * 10
[1] 50
This is especially useful for storing data under a specific name, like we did at the beginning with the iris data. If you run the line of code below, it will print out all of the iris data.
IrisData
We can also access specific variables within the data using the $ symbol. So if we only wanted to see the data about petal length, we can run the following code:
IrisData$petal.length
[1] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 1.5 1.6 1.4 1.1 1.2 1.5 1.3 1.4 1.7 1.5 1.7 1.5 1.0 1.7 1.9 1.6 1.6
[28] 1.5 1.4 1.6 1.6 1.5 1.5 1.4 1.5 1.2 1.3 1.4 1.3 1.5 1.3 1.3 1.3 1.6 1.9 1.4 1.6 1.4 1.5 1.4 4.7 4.5 4.9 4.0
[55] 4.6 4.5 4.7 3.3 4.6 3.9 3.5 4.2 4.0 4.7 3.6 4.4 4.5 4.1 4.5 3.9 4.8 4.0 4.9 4.7 4.3 4.4 4.8 5.0 4.5 3.5 3.8
[82] 3.7 3.9 5.1 4.5 4.5 4.7 4.4 4.1 4.0 4.4 4.6 4.0 3.3 4.2 4.2 4.2 4.3 3.0 4.1 6.0 5.1 5.9 5.6 5.8 6.6 4.5 6.3
[109] 5.8 6.1 5.1 5.3 5.5 5.0 5.1 5.3 5.5 6.7 6.9 5.0 5.7 4.9 6.7 4.9 5.7 6.0 4.8 4.9 5.6 5.8 6.1 6.4 5.6 5.1 5.6
[136] 6.1 5.6 5.5 4.8 5.4 5.6 5.1 5.1 5.9 5.7 5.2 5.0 5.2 5.4 5.1
Those are the basic functions you should know about R moving forward. Now we can explore more tools you can use to explore and analyze a set of data.
Exploring Your Data
Once we have our data, it is important to explore it before beginning analysis. First, you want to come up with the question that you will attempt to answer before analyzing your data. This is important since we want to remain objective throughout the data analysis process.
For this tutorial, we’re interested in the following questions:
- Are sepal and petal dimensions correlated within a single species?
- Do sepal and petal dimensions differ between Iris species?
One way to begin to understand your dataset is to run the str() (structure) function. This outputs lots of information about the dataset. It will show you each column of the data, the class of the column (what type of data it is: a number (num), a word (or character: chr), etc), the number of observations in the column, and some of the data within each column. This is useful for ensuring that each column contains the data you expect. For example, one column in the dataset is sepal length, so I would expect to find in the output of str() that there is a column called sepal length (it is actually called sepal.length, but that is good), it should be a number, there should be 150 observations, and the data should actually be numbers.
In the chunk below I will run str() on the iris dataset to confirm my expectations and make sure that the data looks right.
str(IrisData)
spec_tbl_df [150 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ sepal.length: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ sepal.width : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ petal.length: num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ petal.width : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ variety : chr [1:150] "Setosa" "Setosa" "Setosa" "Setosa" ...
- attr(*, "spec")=
.. cols(
.. sepal.length = col_double(),
.. sepal.width = col_double(),
.. petal.length = col_double(),
.. petal.width = col_double(),
.. variety = col_character()
.. )
- attr(*, "problems")=<externalptr>
One thing that stands out to me after running str() is the “variety” column. For starters, you may want to rename the column to something that’s easier for you to understand, such as “species.” You can do this using the rename() function as explained below. Once you’ve run that code, you can click on the dataset in your Environment and should see the column has been renamed.
#The rename() function allows this format: DataName <- rename(DataName, NewVariableName = OldVariableName)
IrisData <- rename(IrisData, species = variety)
If we want to compare variables between species of irises, this column will be very useful. To make those comparisons easier, I am going to tell R that this variable is categorical. We can group the data into those categories using the as.factor() function below.
IrisData$species <- as.factor(IrisData$species)
#This code tells R to replace the current character species column of IrisData with the new factor species column.
str(IrisData)
spec_tbl_df [150 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ sepal.length: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ sepal.width : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ petal.length: num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ petal.width : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ species : Factor w/ 3 levels "Setosa","Versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
- attr(*, "spec")=
.. cols(
.. sepal.length = col_double(),
.. sepal.width = col_double(),
.. petal.length = col_double(),
.. petal.width = col_double(),
.. variety = col_character()
.. )
- attr(*, "problems")=<externalptr>
#Running str() again shows that species is now a factor with 3 levels which correspond to the 3 different species.
It can also be useful to look at the top and bottom of your dataset using the head() and tail() functions, which show the first 6 rows and last 6 rows respectively. This is useful to ensure that the data makes sense (the data is numeric if you were expecting that) and to make sure that the correct number of rows are present (for example, make sure that the last few rows are not empty). Or, if the data is time dependent, you can use these functions to make sure that the first times are in the first row and the last times are at the end.
#This chunk will output two functions, and it will separate them into two windows if you run the whole chunk. Here, the left window is the head function, and the right window is the tail function. The output windows will always proceed left to right to correspond with your code from top to bottom.
head(IrisData)
tail(IrisData)
A very useful function for data exploration is summary(). This outputs the mean, median, min, max, and first and third quartiles of any numeric data, and the number of observations within our variables. This is an important step in any data exploration. This can be useful for validating your data against external sources. If external sources show that the average sepal length of irises is 100 cm long, but our sepal lengths range from 4.3 to 7.9 cm, something might be wrong. Luckily the average is closer to 5-7 cm, so our data does make sense.
summary(IrisData)
sepal.length sepal.width petal.length petal.width species
Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100 Setosa :50
1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300 Versicolor:50
Median :5.800 Median :3.000 Median :4.350 Median :1.300 Virginica :50
Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
Visualization with Graphs
Now that we’ve spent a substantial amount of time exploring and organizing our data, we’re ready to start analyzing it! The first step here is to visualize our data since up until this point, all we’ve been looking at are numbers (which can be hard for identifying relationships and patterns between variables). When considering what graphs would be best for visualizing our data, we should consider our questions of interest and what types of variables we’re dealing with. As a reminder, our two questions of interest are below:
- Are sepal and petal dimensions correlated within a single species?
- Do sepal and petal dimensions differ between Iris species?
Are sepal and petal dimensions correlated within a single species?
Let’s focus on question number one first. There are a couple different, more specific questions we can look at within this. Such as, the relationship between sepal length and sepal width, or petal length and petal width. Perhaps we can even compare sepal length and petal length, or sepal width and petal width. Wow! There are a ton of different relationships to look at. For our purposes, let’s narrow in on two relationships:
- Sepal length and sepal width
- Sepal length and petal length
Since all of these variables are numerical, a scatterplot would best represent the data. The ggplot function is extremely useful for creating graphs. Below is the code for creating a basic scatterplot.
#Follows the form: ggplot(DataName, aes(x=VariableOne, y=VariableTwo)) + geom_point()
ggplot(IrisData, aes(x=sepal.length, y=sepal.width)) + geom_point()

#Learning check: Try running the code without + geom_point(). What happens?
In the output we see a basic scatterplot without any clear pattern. This could be because we’re looking at data for all three species. Remember, our original question was about whether there were relationships between the variables within a single species. We can either filter the data so that we can plot one species at a time, or we can just color-code the points on the scatterplot by species so we can still look at all of the data (this is the method we’ll use).
ggplot(IrisData, aes(x=sepal.length, y=sepal.width, shape=species)) + geom_point()

#Adding shape=species in the code line tells R to group the points according to species and to differentiate the species using different shapes.
By separating the data points according to species we can start to see some patterns emerging between the variables within each species. However, it still takes a second to differentiate between Versicolor and Virginica since they occupy the same general space on the plot and you don’t immediately notice the difference in shapes. To make it easier to distinguish between the two, we can use color to differentiate the species rather than shape.
ggplot(IrisData, aes(x=sepal.length, y=sepal.width, color=species)) + geom_point()

#Adding color=species in the code line tells R to differentiate the species by color as well as by shape.
Based on this scatterplot, there seems to be a positive correlation between sepal length and sepal width within each species. Say you wanted to present this data in a formal report. You would likely want to clean it up a bit. Fortunately, ggplot has a ton of ways you can spruce up your graphs to look neater and more professional. Let’s take a look at some of those tools.
ggplot(IrisData, aes(x=sepal.length, y=sepal.width, color=species)) + #Basic scatterplot grouped by color
geom_point() + #Adds data points to plot
geom_smooth(method=lm, se=FALSE) + #Adds regression lines
labs(x = "Sepal Length (cm)", y = "Sepal Width (cm)") + #Renames axis labels
labs(col="Species") + #Renames legend
labs(title = "Sepal Width vs. Sepal Length in Three Iris Species") + #Gives the plot a title
theme(plot.title = element_text(hjust = 0.5))# Centers the plot title
`geom_smooth()` using formula 'y ~ x'

This plot looks much nicer and is easier to interpret compared to our initial scatterplot. Now that we have the code all figured out, we can essentially copy and paste the same code but substitute in new variable to look at other relationships as well. Let’s look at the relationship between
ggplot(IrisData, aes(x=sepal.length, y=petal.length, color=species)) +
geom_point() +
geom_smooth(method=lm, se=FALSE) +
labs(x = "Sepal Length (cm)", y = "Petal Length (cm)") +
labs(col="Species") +
labs(title = "Petal Length vs. Sepal Length in Three Iris Species") +
theme(plot.title = element_text(hjust = 0.5))
`geom_smooth()` using formula 'y ~ x'

This scatterplot reveals that there also seems to be a positive correlation between sepal length and petal length within each species, though the strength of that relationship may differ between species. Feel free to use this scatterplot code to visualize relationships between other variables as well.
Do sepal and petal dimensions differ between Iris species?
Our next question of interest deals with comparing dimensions between species. Once again, there are a ton of different, more specific questions we can look at within this. For our purposes, let’s focus on sepal length between species. Since species is a categorical variable, a boxplot would best represent the data. The code for a basic boxplot is below.

There appears to be a difference in sepal length between species (note: determining whether or not that difference is significant is for later statistical testing). Just as we did before, let’s spruce up our plot a bit.
ggplot(IrisData, aes(x=species, y=petal.length, fill=species)) + #Addition of fill=species adds color
geom_boxplot() +
labs(x = "Species", y = "Petal Length (cm)") + #Renames axes
labs(title = "Petal Length for Three Iris Species") + #Gives plot a title
theme(plot.title = element_text(hjust = 0.5)) + #Centers title
theme(legend.position = "none")

Once you get really good with R, you’ll be able to make plots like the one below, where you include the significance bars for pairwise comparisons between each of the species. Even though we’re getting ahead of ourselves here, feel free to play around with the code below to make plots for other variables and look at the p-values for pairwise comparisons between species.

Hypothesis Testing with Statistical Tests
Up until this point we’ve been looking at the data with some questions in mind about relationships in the data. For statistical tests, we need a specific question or hypothesis to test. Our hypothesis is that petal length differs significantly between Iris species. We will test this hypothesis below.
Requirements for Tests
Now we can move on to analyzing our data more critically with statistical testing for specific hypotheses. When using statistical tests, always be sure to check the assumptions made by the particular test you plan to use. This is important because many common statistical tests, including the two-sample t-test we will use here, assume that the datasets being compared are normally distributed. While much biological data is normally distributed, this is not always true, so be sure to explore and understand the behavior of your data before performing tests.
The shapiro.test function allows us to check if our data is normally distributed. If the data is normally distributed, the p-value returned by the shapiro test should be greater than 0.05. If there are multiple groups/populations within a data set (for example, multiple species of iris), it’s important to test for a normal distribution within each of those populations separately. Looking at the distribution as a whole may lead us to think the data is not normally distributed when it actually is within each population. This is actually the case for us, as you can see with the output below.
shapiro.test(IrisData$petal.length) #Not normally distributed as a whole (p)
Shapiro-Wilk normality test
data: IrisData$petal.length
W = 0.87627, p-value = 7.412e-10
shapiro.test(IrisData$petal.length[IrisData$species=="Setosa"]) #Normally distributed
Shapiro-Wilk normality test
data: IrisData$petal.length[IrisData$species == "Setosa"]
W = 0.95498, p-value = 0.05481
shapiro.test(IrisData$petal.length[IrisData$species=="Versicolor"]) #Normally distributed
Shapiro-Wilk normality test
data: IrisData$petal.length[IrisData$species == "Versicolor"]
W = 0.966, p-value = 0.1585
shapiro.test(IrisData$petal.length[IrisData$species=="Virginica"]) #Normally distributed
Shapiro-Wilk normality test
data: IrisData$petal.length[IrisData$species == "Virginica"]
W = 0.96219, p-value = 0.1098
If the data you are using is not normally distributed, test to see if a logarithmic transformation would make the distribution normal. If so, you should use the log-transformed data. If not, continue on with the original, non-transformed data but note in your report that any statistical test results should be interpreted with caution, given that the base requirements for accurate use of the test have not been met.
Since the data for petal length is normally distributed within each species, a log transformation is not necessary in our case. We will proceed with the non-transformed data. However, here is an example of how you would perform a log transformation if you needed to:
#LogPetalLength <- log(petal.length)
Note that each statistical test which assumes normality also has a sample size requirement which can allow for them to produce accurate results using non-normal data. For a two-sample t-test or a one-way ANOVA test, each group is required to have a sample size of at least 15 observations to overcome the need for normality. If your samples do fit this requirement, you can proceed without worrying about normality. This cutoff is different for each type of test, so always be sure to check before you disregard any requirements.
ANOVA and Two-sample T-tests
In order to analyze whether petal length differs significantly between species, we can perform an ANOVA. We do this with the aov() function. It’s best to assign the function to a variable that you can then run a summary of to see the output from the ANOVA test.
anova <- aov(petal.length ~ species, data = IrisData)
summary(anova)
Df Sum Sq Mean Sq F value Pr(>F)
species 2 437.1 218.55 1180 <2e-16 ***
Residuals 147 27.2 0.19
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
The ANOVA test returned a p-value < 2e-16 which is much less than 0.05 (the standard significance level). If you recall from statistics, this gives us evidence that petal length is significantly different for at least one of the groups (species), but we don’t know which. In order to further analyze petal length between species, we can conduct pairwise t-tests to see which species’ petal lengths significantly differ from one another. In order to conduct pairwise comparisons, we need to filter the data into three data subsets, one for each pairwise comparison. We can do this using the filter() function and assign each filtered dataset to a new dataset.
t.test(petal.length ~ species, data = SetosaVersicolor)
Welch Two Sample t-test
data: petal.length by species
t = -39.493, df = 62.14, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Setosa and group Versicolor is not equal to 0
95 percent confidence interval:
-2.939618 -2.656382
sample estimates:
mean in group Setosa mean in group Versicolor
1.462 4.260
t.test(petal.length ~ species, data = SetosaVirginica)
Welch Two Sample t-test
data: petal.length by species
t = -49.986, df = 58.609, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Setosa and group Virginica is not equal to 0
95 percent confidence interval:
-4.253749 -3.926251
sample estimates:
mean in group Setosa mean in group Virginica
1.462 5.552
t.test(petal.length ~ species, data = VersicolorVirginica)
Welch Two Sample t-test
data: petal.length by species
t = -12.604, df = 95.57, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Versicolor and group Virginica is not equal to 0
95 percent confidence interval:
-1.49549 -1.08851
sample estimates:
mean in group Versicolor mean in group Virginica
4.260 5.552
The results from the pairwise comparisons indicate that the mean petal length for the three species are each significantly different from one another. We actually see the same p-values returned by the pairwise t-tests displayed on the box-plot with p-values. This makes sense, since the p-values on the boxplot resulted from pairwise comparisons. Overall, we have evidence to support the hypothesis that petal length differs significantly between Iris species.
Linear Model
We can also use a linear model as a statistical test to look at relationships in the data. We already used a linear model to some degree when we created our scatterplot and included a regression line. However, now we’re going to look at a linear model more quantitatively rather than qualitatively. The lm() function allows us to build a linear model with our data.
#The lm() function takes the form: lm(DependentVariable ~ IndependentVariable, data=DataName)
lmSpecies <- lm(petal.length ~ species, data=IrisData)
summary(lmSpecies)
Call:
lm(formula = petal.length ~ species, data = IrisData)
Residuals:
Min 1Q Median 3Q Max
-1.260 -0.258 0.038 0.240 1.348
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.46200 0.06086 24.02 <2e-16 ***
speciesVersicolor 2.79800 0.08607 32.51 <2e-16 ***
speciesVirginica 4.09000 0.08607 47.52 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.4303 on 147 degrees of freedom
Multiple R-squared: 0.9414, Adjusted R-squared: 0.9406
F-statistic: 1180 on 2 and 147 DF, p-value: < 2.2e-16
The p-value returned with the linear model is < 2.2e-16. This shows us that petal length is dependent on/explained by species. This is what we expected based on earlier statistical tests. For the sake of this tutorial, let’s explore another linear model that looks at petal length sepal width.
lmSepalWidth <- lm(petal.length ~ sepal.width, data=IrisData)
summary(lmSepalWidth)
Call:
lm(formula = petal.length ~ sepal.width, data = IrisData)
Residuals:
Min 1Q Median 3Q Max
-3.7721 -1.4164 0.1719 1.2094 4.2307
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.0632 0.9289 9.757 < 2e-16 ***
sepal.width -1.7352 0.3008 -5.768 4.51e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.6 on 148 degrees of freedom
Multiple R-squared: 0.1836, Adjusted R-squared: 0.178
F-statistic: 33.28 on 1 and 148 DF, p-value: 4.513e-08
This linear model returned a p-value of 4.513e-8. While this is still a very significant p-value, we see that our model which used species rather than sepal width was a better model. We can represent the difference in how well these two modes fit the data with an ANOVA that compares the two models.
anova(lmSepalWidth, lmSpecies, test='F')
Analysis of Variance Table
Model 1: petal.length ~ sepal.width
Model 2: petal.length ~ species
Res.Df RSS Df Sum of Sq F Pr(>F)
1 148 379.09
2 147 27.22 1 351.87 1900.1 < 2.2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
The ANOVA returned a p-value < 2.2e-16. This is interpreted as having sufficient evidence that the second model in the code line (species model) is a better fit for the data than the first model in the code line (sepal width model). So while both models may be a good fit for the data, the model with species is a better fit overall. We can also consider whether a linear model that combines both variables would be an even better fit than a model that only considers species.
lmSpeciesSepalWidth <- lm(petal.length ~ species + sepal.width, data=IrisData)
summary(lmSpeciesSepalWidth)
Call:
lm(formula = petal.length ~ species + sepal.width, data = IrisData)
Residuals:
Min 1Q Median 3Q Max
-1.13073 -0.22613 -0.01516 0.23307 1.52706
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.17920 0.33753 -0.531 0.596
speciesVersicolor 3.11303 0.10234 30.420 < 2e-16 ***
speciesVirginica 4.30736 0.09130 47.179 < 2e-16 ***
sepal.width 0.47876 0.09707 4.932 2.19e-06 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3998 on 146 degrees of freedom
Multiple R-squared: 0.9497, Adjusted R-squared: 0.9487
F-statistic: 919.7 on 3 and 146 DF, p-value: < 2.2e-16
anova(lmSpecies, lmSpeciesSepalWidth, test='F')
Analysis of Variance Table
Model 1: petal.length ~ species
Model 2: petal.length ~ species + sepal.width
Res.Df RSS Df Sum of Sq F Pr(>F)
1 147 27.223
2 146 23.335 1 3.8879 24.326 2.186e-06 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
The ANOVA returned a p-value of 2.186e-6. This is interpreted as having sufficient evidence that the combined model is a better fit than the model that only considers species. This makes sense since our earlier analyses revealed that all of the variables in this dataset seemed to be closely related with one another.
Congratulations! You just got through the R for Dummies (BIOL208 Edition) tutorial, and that’s no easy task. The world of coding in R still has so much for you to discover, but you have the skills now to get started with it. If this tutorial has left you craving for more data analysis and R knowledge, check out the additional tools below. Happy coding!
LS0tCnRpdGxlOiAiR3JvdXAgUHJvamVjdCAxIgphdXRob3I6ICJJYW4gTWF3biwgS2FpdGxpbiBNY0xhaW4sIGFuZCBFbWlseSBTY2hvbGZpZWxkIgpkYXRlOiAiMjEgRmViIDIwMjIiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CnN1YnRpdGxlOiBCaW9sb2d5IDM2OC82NjQgQnVja25lbGwgVW5pdmVyc2l0eQotLS0KCiMgUiBmb3IgRHVtbWllcyAoQklPTDIwOCBFZGl0aW9uKQoKV2VsY29tZSB0byB0aGlzIFIgdHV0b3JpYWwgZm9yIEJJT0wyMDghIFRoaXMgaXMgZGVzaWduZWQgZm9yIHNvbWVvbmUgd2hvIGlzIGJyYW5kIG5ldyB0byBSLCBzbyB3ZSBhcmUgZ29pbmcgdG8gc3RhcnQgd2l0aCB0aGUgdmVyeSBiYXNpY3MuIFRvIG1ha2UgdGhpcyBpbnRlcmVzdGluZywgd2UnbGwgYmUgbG9va2luZyBhdCBhIGRhdGFzZXQgb24gaXJpc2VzIHNpbmNlIHBsYW50cyBhcmUgZXh0cmVtZWx5IGltcG9ydGFudCB0byB0aGUgc3R1ZHkgb2YgZWNvbG9neSBhbmQgZXZvbHV0aW9uLiBUbyBiZXN0IGZvbGxvdyBhbG9uZywgeW91IHNob3VsZCBoYXZlIGEgbmV3IG1hcmtkb3duIGZpbGUgb3BlbiBpbiBSIHN0dWRpbyB3aGVyZSB5b3UgY2FuIGNvcHkgYW5kIHBhc3RlIGxpbmUgc29mIGNvZGUgZnJvbSB0aGlzIHR1dG9yaWFsIGZvciB5b3UgdG8gcHJhY3RpY2UgcnVubmluZyBvbiB5b3VyIG93bi4KClR5cGljYWxseSwgd2hlbiBkb2luZyBkYXRhIGFuYWx5c2lzIGluIFIsIHdlIHdhbnQgdG8gYmVnaW4gYnkgbG9hZGluZyBpbiB0aGUgZGF0YSBhbmQgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIHVzZS4KCiMjIExvYWRpbmcgTGlicmFyaWVzIGFuZCBEYXRhICAKUiBoYXMgbWFueSBidWlsdCBpbiBmdW5jdGlvbnMgdGhhdCB3aWxsIGFsbG93IHVzIHRvIHBlcmZvcm0gYWxsIGtpbmRzIG9mIGFjdGlvbnMuIEhvd2V2ZXIsIHNvbWV0aW1lcyBpdCBpcyB1c2VmdWwgdG8gbG9hZCBzb21lIGFkZGl0aW9uYWwgZnVuY3Rpb25zIHRoYXQgb3RoZXIgUiB1c2VycyBoYXZlIGNyZWF0ZWQuIFdlIGRvIHRoaXMgYnkgbG9hZGluZyBpbiBsaWJyYXJpZXMuIEluIHRoZSBjb2RlIGNodW5rIGJlbG93ICh0aGUgZ3JleSBib3g7IHRoaXMgaXMgd2hlcmUgY29kZSBpcyB0eXBlZCBhbmQgcnVuKSB5b3UgY2FuIHNlZSB0aGF0IEkgaGF2ZSBsb2FkZWQgaW4gc29tZSBsaWJyYXJpZXMuCmBgYHtyIExvYWQgTGlicmFyaWVzLCByZXN1bHRzPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIEluc3RhbGwgcGFja2FnZXMgYW5kIGxvYWQgdGhlaXIgbGlicmFyaWVzIGhlcmUuCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpOyBsaWJyYXJ5KHRpZHl2ZXJzZSkKaWYgKCFyZXF1aXJlKCJjb3dwbG90IikpIGluc3RhbGwucGFja2FnZXMoImNvd3Bsb3QiKTsgbGlicmFyeShjb3dwbG90KQppZiAoIXJlcXVpcmUoIlVzaW5nUiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJVc2luZ1IiKTsgbGlicmFyeShVc2luZ1IpCmlmICghcmVxdWlyZSgiZ2dwdWJyIikpIGluc3RhbGwucGFja2FnZXMoImdncHViciIpOyBsaWJyYXJ5KGdncHVicikKaWYgKCFyZXF1aXJlKCJyZWFkeGwiKSkgaW5zdGFsbC5wYWNrYWdlcygicmVhZHhsIik7IGxpYnJhcnkocmVhZHhsKQpgYGAKCiMjIyBMaWJyYXJpZXMKRm9yIHNvbWUgZXhhbXBsZXMsIG9uZSBsaWJyYXJ5IGlzIGNhbGxlZCB0aWR5dmVyc2UuIEl0IGNvbnRhaW5zIGEgdG9uIG9mIHVzZWZ1bCB0b29scywgYnV0IHRoZSBvbmUgbW9zdCByZWxldmFudCB0byB0aGlzIHR1dG9yaWFsIGlzIGNhbGxlZCAqKmdncGxvdCoqLiAqKmdncGxvdCoqIGFsbG93cyB1cyB0byBjcmVhdGUgYWxsIGtpbmRzIG9mIHBsb3RzIHRvIHZpc3VhbGl6ZSBvdXIgZGF0YSwgd2hpY2ggeW91IHdpbGwgbGVhcm4gbW9yZSBhYm91dCBiZWxvdy4gWW91IGNhbiBhbHNvIHNlZSB0aGUgbGlicmFyeSBjYWxsZWQgKipjb3dwbG90KiouICoqY293cGxvdCoqIGlzIHVzZWZ1bCBhcyBpdCBhbGxvd3MgdXMgdG8gZWFzaWx5IGNoYW5nZSB0aGUgYWVzdGhldGljcyBvZiBvdXIgZ3JhcGhzLCBhbmQga2VlcCB0aGUgZGVzaWducyBjb25zaXN0ZW50IGJldHdlZW4gZGlmZmVyZW50IGdyYXBocy4gRmluYWxseSwgeW91IGNhbiBzZWUgdGhlIGxpYnJhcnkgKipyZWFkeGwqKi4gVGhpcyBpcyB1c2VmdWwgZm9yIGV4YWN0bHkgd2hhdCBpdCBzb3VuZHMgbGlrZS4uLiByZWFkaW5nIE1pY3Jvc29mdCBFeGNlbCBmaWxlcyEgVGhpcyBicmluZyB1cyB0byB0aGUgbmV4dCBzdGVwLCBlbnRlcmluZyBkYXRhIGludG8gUi4KCiMjIyBEYXRhCkluIHRoZSBjb2RlIGNodW5rIGJlbG93IEkgYW0gZ29pbmcgdG8gcmVhZCBpbiBzb21lIGRhdGEgcmVnYXJkaW5nIGZlYXR1cmVzIG9mIGRpZmZlcmVudCBzcGVjaWVzIG9mIGlyaXMgKHRoZSBmbG93ZXIpLiBUaGVyZSBhcmUgYSBmZXcgbWFpbiBwYXJ0cyBvZiB0aGUgY29kZSB0byB0aGluayBhYm91dCB3aGVuIGxvYWRpbmcgaW4gZGF0YS4gRmlyc3QsIHRoZSAqKnJlYWRfY3N2KCkqKiBmdW5jdGlvbiB0ZWxscyBSIHRvIGxvYWQgaW4gYSBjb21tYSBzZXBhcmF0ZWQgdmFsdWVzIChjc3YpIGZpbGUgd2l0aCB0aGUgbmFtZSBvZiB0aGUgZmlsZSBpbiB0aGUgcGFyZW50aGVzZXMuIEhlcmUsIHlvdSBjYW4gc2VlIHRoYXQgb3VyIGRhdGEgaXMgY2FsbGVkICJpcmlzLmNzdiIuIEl0IGlzIHZlcnkgaW1wb3J0YW50IHRvIHR5cGUgdGhlIGZpbGUgbmFtZSBleGFjdGx5IGFzIGl0IGlzIHNhdmVkIG9uIHlvdXIgY29tcHV0ZXIsIG90aGVyd2lzZSBSIHdpbGwgbm90IGJlIGFibGUgdG8gZmluZCBpdC4gT25jZSB0aGUgZGF0YSBpcyBsb2FkZWQgaW4sIHdlIG5lZWQgdG8gY2FsbCBpdCBzb21ldGhpbmcuIFRoYXQgaXMgd2hhdCB0aGUgIklyaXNEYXRhIDwtIiBwYXJ0IG9mIHRoZSBjb2RlIG1lYW5zLiBJbiBFbmdsaXNoLCBpdCB0cmFuc2xhdGVzIHRvOiBJcmlzRGF0YSBpcyB0aGUgZGF0YSBmb3VuZCBpbiB0aGUgY3N2IGZpbGUgImlyaXMuY3N2Ii4gV2hlbiB5b3UgcmVhZCBpbiBhIGRhdGEgZmlsZSwgeW91IHdpbGwgc2VlIGl0IGFwcGVhciBpbiB5b3VyICJFbnZpcm9ubWVudCIgb24gdGhlIHJpZ2h0IG9mIFIgc3R1ZGlvLiBJZiB5b3UgY2xpY2sgb24gIklyaXNEYXRhIiBpbiB5b3VyIEVudmlyb25tZW50LCBhIG5ldyB0YWIgd2lsbCBhcHBlYXIgd2l0aCBhbGwgb2YgdGhlIGRhdGEuIApgYGB7ciBSZWFkaW5nIGluIERhdGF9CklyaXNEYXRhIDwtIHJlYWRfY3N2ICgiaXJpcy5jc3YiKQpgYGAKCldoYXQgaGFwcGVucyBpZiB5b3VyIGRhdGEgaXMgaW4gYW4gZXhjZWwgZmlsZSBpbnN0ZWFkIG9mIGEgY3N2IGZpbGU/IEZlYXIgbm90ISBEYXRhIGNhbiBhbHNvIGJlIGxvYWRlZCBpbiBmcm9tIGFuIGV4Y2VsIGZpbGUgdXNpbmcgdGhlICoqcmVhZF9leGNlbCgpKiogZnVuY3Rpb24gaW5zdGVhZCBvZiAqKnJlYWRfY3N2KCkqKi4gSW4gYSBub3JtYWwgZGF0YSBhbmFseXNpcywgeW91IHdvdWxkIG9ubHkgcmVhZCBpbiB0aGUgZGF0YSBvbmNlIHVzaW5nICplaXRoZXIqIHRoZSAqKnJlYWRfY3N2KCkqKiAqb3IqICoqcmVhZF9leGNlbCgpKiogZnVuY3Rpb25zLiBZb3VyIGRhdGEgd2lsbCBvbmx5IHJlYWQgaW4gcHJvcGVybHkgaWYgdGhlIGZpbGUgdHlwZSBtYXRjaGVzIHRoZSBmdW5jdGlvbiB5b3UncmUgdXNpbmcsIHNvIHBheSBhdHRlbnRpb24gdG8gaG93IHlvdXIgZGF0YSBpcyBzYXZlZCBiZWZvcmUgeW91IHJlYWQgaXQgaW4hCgojIyBVc2luZyBSIChUaGUgQmFzaWNzKSAgCk5vdyB0aGF0IHdlIGhhdmUgdGhlIHBpZWNlcyB3ZSBuZWVkLCB3ZSBjYW4gc3RhcnQgbGVhcm5pbmcgYWJvdXQgUi4gWW91IGhhdmUgYWxyZWFkeSBzZWVuIGEgZmV3IGFzcGVjdHMgb2YgUiBpbiB0aGUgbGFzdCBzZWN0aW9uLCBidXQgaGVyZSB3ZSB3aWxsIGdvIGludG8gc29tZSBtb3JlIGRldGFpbCBhYm91dCB0aGUgYmFzaWMgZnVuY3Rpb25zIG9mIFIgdG8gZ2V0IHlvdSBzdGFydGVkIHdpdGggYW5hbHl6aW5nIGRhdGEuCgpUaGlzIGRvY3VtZW50IGlzIGFuIFIgbWFya2Rvd24gZmlsZS4gVGhlIGhpZ2hsaWdodHMgb2YgYSBtYXJrZG93biBmaWxlIGlzIHRoYXQgeW91IGNhbiBoYXZlIG1vc3RseSByZWd1bGFyIHRleHQgKG5vdCBjb2RlKSBidXQgc3RpbGwgaW5jbHVkZSBjb2RlIGFuZCB0aGVpciBvdXRwdXQgIGluIHNwZWNpZmljIHNlY3Rpb25zLiBUaGlzIGlzIGVzcGVjaWFsbHkgdXNlZnVsIGFzIGl0IGFsbG93cyBmb3IgbG90cyBvZiBleHBsYW5hdGlvbiBvZiB3aGF0IHRoZSBjb2RlIGRvZXMsIGxpa2Ugd2UgbmVlZCB0byBkbyBoZXJlIGZvciBhIHR1dG9yaWFsLiBNYXJrZG93bnMgYXJlIGFsc28gY29udmVuaWVudCBiZWNhdXNlIHRoZXkgY2FuIGJlIGNvbnZlcnRlZCB0byBtYW55IGRpZmZlcmVudCBmb3JtYXRzIHN1Y2ggYXMgYSBQREYgKGxpa2UgeW91J3JlIHJlYWRpbmcpLCBhbiBodG1sLCBhbmQgb3RoZXJzLgoKQXMgbWVudGlvbmVkIGJlZm9yZSwgdGhlIGdyZXkgc2VjdGlvbnMgYXJlIGNhbGxlZCBjb2RlIGNodW5rcy4gVGhpcyBpcyB3aGVyZSB0aGUgYWN0dWFsIGNvZGUgaXMgd3JpdHRlbiBhbmQgcmFuLiBZb3UgY2FuIGluc2VydCBhIGNvZGUgY2h1bmsgdG8geW91ciBtYXJrZG93biBmaWxlIGJ5IGNsaWNraW5nIHRoZSBncmVlbiBib3ggd2l0aCAiXiteQyIgYXQgdGhlIHRvcCBvZiBSIHN0dWRpby4gV2hlbiB5b3UgZG8gdGhpcywgYSBkcm9wLWRvd24gbWVudSBhcHBlYXJzIHdoZXJlIHlvdSBjYW4gY2hvb3NlIGEgY29kaW5nIGxhbmd1YWdlIChzaW5jZSB0aGlzIGlzIGFib3V0IFIsIHdlIHdpbGwgb25seSB1c2UgdGhhdCkuIFJlZmVyIHRvIEZpZ3VyZSAxIGlmIHlvdSBjYW4ndCBmaW5kIHRoZSBjb2RlIGNodW5rIGJ1dHRvbi4KCiFbQWRkaW5nIGEgTmV3IENvZGUgQ2h1bmtdKC4uL1R1dG9yaWFsX1Byb2plY3RfOC9JbWFnZXMvQ29kZUNodW5rSW1hZ2UucG5nKQoKSW4gdGhlIHRvcCBsaW5lIG9mIHlvdXIgbmV3IGNvZGUgY2h1bmssIHlvdSdsbCBzZWUgKipgYGB7cn0qKi4gVGhpcyBjYW4gYmUgdXNlZCB0byBuYW1lIHlvdXIgY29kZSBjaHVua3MgaWYgeW91IHdpc2guIFRoaXMgY2FuIGhlbHAga2VlcCB5b3VyIHRob3VnaHRzIG9yZ2FuaXplZCBhbmQgaXMgYWN0dWFsbHkgYW4gaW1wb3J0YW50IHBhcnQgb2Yga25pdHRpbmcgeW91ciBmaWxlLi4uU2F5IHdoYXQ/Pz8gV2UncmUgZ29pbmcgdG8gYmUga25pdHRpbmc/IERvbid0IHdvcnJ5LCB3ZSdsbCBleHBsYWluICphbGwqIHRoZSBkZXRhaWxzIGFib3V0IGtuaXR0aW5nIGluIHRoZSBsYXRlciBzZWN0aW9ucyBvZiB0aGlzIHR1dG9yaWFsLiBGb3Igbm93IGp1c3Qga25vdyB0aGF0IG5hbWluZyB5b3VyIGNvZGUgY2h1bmtzIGNhbiBoZWxwIG9yZ2FuaXplIHlvdXIgdGhvdWdodHMgYW5kIGNhbiBzYXZlIHlvdSBwcm9ibGVtcyB3aXRoIGtuaXR0aW5nIGxhdGVyIGRvd24gdGhlIHJvYWQgaWYgeW91IG1ha2Ugc3VyZSB0byBuYW1lIHlvdXIgZWFjaCBvZiB5b3VyIGNvZGUgY2h1bmtzIHNvbWV0aGluZyB1bmlxdWUuCmBgYHtyIENvZGUgQ2h1bmsgRXhhbXBsZX0KI0V4YW1wbGUgY29kZSBjaHVuawo0KzEKI1RoaXMgbGluZSB3aWxsIG5vdCBydW4KYGBgCgpDb2RlIHdpdGhpbiBjaHVua3MgY2FuIGJlIHJ1biBpbiBhIGZldyB3YXlzOiAgCgoxLiBJbiB0aGUgdG9wIHJpZ2h0IG9mIGEgY2h1bmsgaXMgYSBncmVlbiBwbGF5IGJ1dHRvbiB0aGF0IHdpbGwgcnVuIGV2ZXJ5IGxpbmUgb2YgY29kZSBpbiB0aGUgY2h1bmsuICAKMi4gUGxhY2luZyB5b3VyIGN1cnNvciBvbiBhIGxpbmUgeW91IHdhbnQgdG8gcnVuLCBvciBoaWdobGlnaHQgaXQsIGFuZCBoaXQgY29tbWFuZCArIGVudGVyIChvciBjb250cm9sICsgZW50ZXIpLiAgCjMuIENsaWNrIHRoZSBydW4gYnV0dG9uIGluIHRoZSB0b3Agb2YgdGhlIHNjcmVlbiwgd2hpY2ggd2lsbCBicmluZyB1cCBhIGZldyBvcHRpb25zIGZvciBydW5uaW5nIGNvZGUuIFlvdSBjYW4gcnVuIGFsbCBvZiB0aGUgY29kZSBjaHVua3MgaW4geW91ciBkb2N1bWVudCBhdCBvbmNlIChpbiBvcmRlciBmcm9tIHRvcCB0byBib3R0b20pIHdpdGggdGhpcyBvcHRpb24uIFRoaXMgaXMgdXNlZnVsIGZvciBlbnN1cmluZyB5b3VyIGNvZGUgaXMgZnVuY3Rpb25hbCB3aGVuIGZpbmFsaXppbmcgYSBkb2N1bWVudC4gIApGaWd1cmUgMiBvdXRsaW5lcyB3aGVyZSB5b3UgY2FuIGZpbmQgZWFjaCBvZiB0aGVzZS4KCiFbUnVubmluZyBDb2RlXSguLi9UdXRvcmlhbF9Qcm9qZWN0XzgvSW1hZ2VzL1J1bm5pbmdDb2RlLnBuZykKCkxvb2tpbmcgYXQgdGhlIGV4YW1wbGUgY29kZSBjaHVuayBhYm92ZSwgdGhlcmUgYSBmZXcgcG9pbnRzIHRvIG1ha2UgYWJvdXQgY29kaW5nIGluIFIuIEZpcnN0LCB5b3UgY2FuIHNlZSBhIGdyZWVuIGxpbmUgdGhhdCBzdGFydHMgd2l0aCBhICIjIi4gVGhlIGhhc2h0YWcvbnVtYmVyL3BvdW5kIHN5bWJvbCB0ZWxscyBSIHRoYXQgdGhpcyBsaW5lIGlzIGEgY29tbWVudCwgYW5kIHRoYXQgaXQgc2hvdWxkIG5vdCBiZSBydW4gYXMgY29kZS4gSWYgeW91IHJ1biB0aGUgY29kZSBjaHVuayB5b3Ugd2lsbCBzZWUgdGhhdCB0aGF0IGxpbmUgaXMgc2tpcHBlZCwgYW5kIHRoZSBvbmx5IG91dHB1dCBjb21lcyBmcm9tIHRoZSBhZGRpdGlvbiBmb3VuZCBpbiB0aGUgbmV4dCBsaW5lICh0aGUgb3V0cHV0IHNob3VsZCBiZSA1IHNpbmNlIDQrMT01KS4gQ29tbWVudHMgYXJlIHZlcnkgdXNlZnVsIGZvciBleHBsYWluaW5nIHlvdXIgY29kZSBhcyB5b3Ugd3JpdGUgaXQuIFRoaXMgaXMgaGVscGZ1bCBmb3IgeW91cnNlbGYgaW4gdGhlIGZ1dHVyZSwgc28geW91IGNhbiByZW1pbmQgeW91cnNlbGYgaG93IGRpZmZlcmVudCBjb2RlIHdvcmtzLCBhbmQgZm9yIG90aGVyIHBlb3BsZSByZWFkaW5nIHRocm91Z2ggb3IgcmVmZXJlbmNpbmcgeW91ciBjb2RlLgoKQW5vdGhlciB1c2VmdWwgYml0IG9mIGluZm9ybWF0aW9uIGlzIGhvdyB0byBhc3NpZ24gdmFsdWVzIHRvIG9iamVjdHMuIEVzc2VudGlhbGx5LCB0aGlzIGlzIGEgd2F5IG9mIG5hbWluZyB0aGluZ3MuIFlvdSBoYXZlIGFjdHVhbGx5IGFscmVhZHkgc2VlbiB0aGlzIGluIGFjdGlvbiwgd2hlcmUgd2UgYXNzaWduZWQgb3VyIGlyaXMgZGF0YSB0byB0aGUgb2JqZWN0IElyaXNEYXRhIHVzaW5nIHRoZSBhc3NpZ24gb3BlcmF0b3IgKio8LSoqLiBMZXRzIGdvIHRvIHRoZSBuZXh0IGNvZGUgY2h1bmsgdG8gc2VlIGFuIGV4YW1wbGUgYW5kIG5vdGljZSBob3cgYWxsIG9mIHRoZXNlIHZhbHVlcy92YXJpYWJsZXMgd2lsbCBnZXQgc3RvcmVkIGluIHRoZSBFbnZpcm9ubWVudC4KYGBge3IgQXNzaWdufQojRXNzZW50aWFsbHksIHRoZSA8LSBtZWFucyAic3RvcmUgdGhpcyB2YWx1ZSB1bmRlciB0aGlzIG5hbWUsIiBzbyB5b3UgY2FuIHRoaW5rIG9mIHRoZSBzeW1ib2wgYXMgdGhlIHdvcmQgImlzIiBvciAiZXF1YWxzLiIgCnRoaXMgPC0gInRoYXQiCgojSW4gdGhlIGxpbmUgYWJvdmUgd2UgYXJlIHN0b3JpbmcgdGhlIHdvcmQgdGhhdCB1bmRlciB0aGUgbmFtZSB0aGlzLiBTbyB0aGUgY29kZSB3b3VsZCByZWFkIGluIEVuZ2xpc2ggInRoaXMgaXMgdGhhdCIuIEFuZCBpZiB3ZSBwcmludCBvdXQgdGhlIG9iamVjdCAoYS5rLmEuIHJ1biB0aGUgY29kZSkgInRoaXMsIiBpdCB3aWxsIG91dHB1dCB0aGUgd29yZCAidGhhdC4iIFRyeSB0aGlzIG91dCB5b3Vyc2VsZiEgSW4geW91ciBtYXJrZG93biBmaWxlLCB0cnkgcnVubmluZyB0aGUgbmV4dCBsaW5lLCBidXQgYmUgc3VyZSB0byBydW4gdGhlIGxpbmUgYWJvdmUgZmlyc3QuCnRoaXMKCiNPdGhlciBleGFtcGxlcwpuIDwtIDUKeiA8LSAxMCAKbit6CnovbgooeituKS8zIC0+IGZpdmUKZml2ZSAqIDEwCmBgYAoKVGhpcyBpcyBlc3BlY2lhbGx5IHVzZWZ1bCBmb3Igc3RvcmluZyBkYXRhIHVuZGVyIGEgc3BlY2lmaWMgbmFtZSwgbGlrZSB3ZSBkaWQgYXQgdGhlIGJlZ2lubmluZyB3aXRoIHRoZSBpcmlzIGRhdGEuIElmIHlvdSBydW4gdGhlIGxpbmUgb2YgY29kZSBiZWxvdywgaXQgd2lsbCBwcmludCBvdXQgYWxsIG9mIHRoZSBpcmlzIGRhdGEuCmBgYHtyIFByaW50aW5nIERhdGF9CklyaXNEYXRhCmBgYAoKV2UgY2FuIGFsc28gYWNjZXNzIHNwZWNpZmljIHZhcmlhYmxlcyB3aXRoaW4gdGhlIGRhdGEgdXNpbmcgdGhlICoqJCoqIHN5bWJvbC4gU28gaWYgd2Ugb25seSB3YW50ZWQgdG8gc2VlIHRoZSBkYXRhIGFib3V0IHBldGFsIGxlbmd0aCwgd2UgY2FuIHJ1biB0aGUgZm9sbG93aW5nIGNvZGU6CmBgYHtyIFByaW50IE91dCBTcGVjaWZpYyBWYXJpYWJsZX0KSXJpc0RhdGEkcGV0YWwubGVuZ3RoCmBgYAoKVGhvc2UgYXJlIHRoZSBiYXNpYyBmdW5jdGlvbnMgeW91IHNob3VsZCBrbm93IGFib3V0IFIgbW92aW5nIGZvcndhcmQuIE5vdyB3ZSBjYW4gZXhwbG9yZSBtb3JlIHRvb2xzIHlvdSBjYW4gdXNlIHRvIGV4cGxvcmUgYW5kIGFuYWx5emUgYSBzZXQgb2YgZGF0YS4KCiMjIEV4cGxvcmluZyBZb3VyIERhdGEgIApPbmNlIHdlIGhhdmUgb3VyIGRhdGEsIGl0IGlzIGltcG9ydGFudCB0byBleHBsb3JlIGl0IGJlZm9yZSBiZWdpbm5pbmcgYW5hbHlzaXMuIEZpcnN0LCB5b3Ugd2FudCB0byBjb21lIHVwIHdpdGggdGhlIHF1ZXN0aW9uIHRoYXQgeW91IHdpbGwgYXR0ZW1wdCB0byBhbnN3ZXIgKmJlZm9yZSBhbmFseXppbmcgeW91ciBkYXRhKi4gVGhpcyBpcyBpbXBvcnRhbnQgc2luY2Ugd2Ugd2FudCB0byByZW1haW4gb2JqZWN0aXZlIHRocm91Z2hvdXQgdGhlIGRhdGEgYW5hbHlzaXMgcHJvY2Vzcy4KCkZvciB0aGlzIHR1dG9yaWFsLCB3ZSdyZSBpbnRlcmVzdGVkIGluIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOiAgCgoxLiBBcmUgc2VwYWwgYW5kIHBldGFsIGRpbWVuc2lvbnMgY29ycmVsYXRlZCB3aXRoaW4gYSBzaW5nbGUgc3BlY2llcz8gIAoyLiBEbyBzZXBhbCBhbmQgcGV0YWwgZGltZW5zaW9ucyBkaWZmZXIgYmV0d2VlbiBJcmlzIHNwZWNpZXM/CgpPbmUgd2F5IHRvIGJlZ2luIHRvIHVuZGVyc3RhbmQgeW91ciBkYXRhc2V0IGlzIHRvIHJ1biB0aGUgKipzdHIoKSoqIChzdHJ1Y3R1cmUpIGZ1bmN0aW9uLiBUaGlzIG91dHB1dHMgbG90cyBvZiBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGF0YXNldC4gSXQgd2lsbCBzaG93IHlvdSBlYWNoIGNvbHVtbiBvZiB0aGUgZGF0YSwgdGhlIGNsYXNzIG9mIHRoZSBjb2x1bW4gKHdoYXQgdHlwZSBvZiBkYXRhIGl0IGlzOiBhIG51bWJlciAobnVtKSwgYSB3b3JkIChvciBjaGFyYWN0ZXI6IGNociksIGV0YyksIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGluIHRoZSBjb2x1bW4sIGFuZCBzb21lIG9mIHRoZSBkYXRhIHdpdGhpbiBlYWNoIGNvbHVtbi4gVGhpcyBpcyB1c2VmdWwgZm9yIGVuc3VyaW5nIHRoYXQgZWFjaCBjb2x1bW4gY29udGFpbnMgdGhlIGRhdGEgeW91IGV4cGVjdC4gRm9yIGV4YW1wbGUsIG9uZSBjb2x1bW4gaW4gdGhlIGRhdGFzZXQgaXMgc2VwYWwgbGVuZ3RoLCBzbyBJIHdvdWxkIGV4cGVjdCB0byBmaW5kIGluIHRoZSBvdXRwdXQgb2Ygc3RyKCkgdGhhdCB0aGVyZSBpcyBhIGNvbHVtbiBjYWxsZWQgc2VwYWwgbGVuZ3RoIChpdCBpcyBhY3R1YWxseSBjYWxsZWQgc2VwYWwubGVuZ3RoLCBidXQgdGhhdCBpcyBnb29kKSwgaXQgc2hvdWxkIGJlIGEgbnVtYmVyLCB0aGVyZSBzaG91bGQgYmUgMTUwIG9ic2VydmF0aW9ucywgYW5kIHRoZSBkYXRhIHNob3VsZCBhY3R1YWxseSBiZSBudW1iZXJzLgoKSW4gdGhlIGNodW5rIGJlbG93IEkgd2lsbCBydW4gc3RyKCkgb24gdGhlIGlyaXMgZGF0YXNldCB0byBjb25maXJtIG15IGV4cGVjdGF0aW9ucyBhbmQgbWFrZSBzdXJlIHRoYXQgdGhlIGRhdGEgbG9va3MgcmlnaHQuCmBgYHtyIFVzaW5nIHN0cigpfQpzdHIoSXJpc0RhdGEpCmBgYAoKT25lIHRoaW5nIHRoYXQgc3RhbmRzIG91dCB0byBtZSBhZnRlciBydW5uaW5nICoqc3RyKCkqKiBpcyB0aGUgInZhcmlldHkiIGNvbHVtbi4gRm9yIHN0YXJ0ZXJzLCB5b3UgbWF5IHdhbnQgdG8gcmVuYW1lIHRoZSBjb2x1bW4gdG8gc29tZXRoaW5nIHRoYXQncyBlYXNpZXIgZm9yIHlvdSB0byB1bmRlcnN0YW5kLCBzdWNoIGFzICJzcGVjaWVzLiIgWW91IGNhbiBkbyB0aGlzIHVzaW5nIHRoZSAqKnJlbmFtZSgpKiogZnVuY3Rpb24gYXMgZXhwbGFpbmVkIGJlbG93LiBPbmNlIHlvdSd2ZSBydW4gdGhhdCBjb2RlLCB5b3UgY2FuIGNsaWNrIG9uIHRoZSBkYXRhc2V0IGluIHlvdXIgRW52aXJvbm1lbnQgYW5kIHNob3VsZCBzZWUgdGhlIGNvbHVtbiBoYXMgYmVlbiByZW5hbWVkLgpgYGB7ciBSZW5hbWluZyB2YXJpYWJsZX0KI1RoZSByZW5hbWUoKSBmdW5jdGlvbiBhbGxvd3MgdGhpcyBmb3JtYXQ6IERhdGFOYW1lIDwtIHJlbmFtZShEYXRhTmFtZSwgTmV3VmFyaWFibGVOYW1lID0gT2xkVmFyaWFibGVOYW1lKQpJcmlzRGF0YSA8LSByZW5hbWUoSXJpc0RhdGEsIHNwZWNpZXMgPSB2YXJpZXR5KQpgYGAKCklmIHdlIHdhbnQgdG8gY29tcGFyZSB2YXJpYWJsZXMgYmV0d2VlbiBzcGVjaWVzIG9mIGlyaXNlcywgdGhpcyBjb2x1bW4gd2lsbCBiZSB2ZXJ5IHVzZWZ1bC4gVG8gbWFrZSB0aG9zZSBjb21wYXJpc29ucyBlYXNpZXIsIEkgYW0gZ29pbmcgdG8gdGVsbCBSIHRoYXQgdGhpcyB2YXJpYWJsZSBpcyBjYXRlZ29yaWNhbC4gV2UgY2FuIGdyb3VwIHRoZSBkYXRhIGludG8gdGhvc2UgY2F0ZWdvcmllcyB1c2luZyB0aGUgYXMuZmFjdG9yKCkgZnVuY3Rpb24gYmVsb3cuCmBgYHtyIENoYW5naW5nIFZhcmlhYmxlIHR5cGUgdXNpbmcgYXMuZmFjdG9yKCl9CklyaXNEYXRhJHNwZWNpZXMgPC0gYXMuZmFjdG9yKElyaXNEYXRhJHNwZWNpZXMpCiNUaGlzIGNvZGUgdGVsbHMgUiB0byByZXBsYWNlIHRoZSBjdXJyZW50IGNoYXJhY3RlciBzcGVjaWVzIGNvbHVtbiBvZiBJcmlzRGF0YSB3aXRoIHRoZSBuZXcgZmFjdG9yIHNwZWNpZXMgY29sdW1uLgoKc3RyKElyaXNEYXRhKQojUnVubmluZyBzdHIoKSBhZ2FpbiBzaG93cyB0aGF0IHNwZWNpZXMgaXMgbm93IGEgZmFjdG9yIHdpdGggMyBsZXZlbHMgd2hpY2ggY29ycmVzcG9uZCB0byB0aGUgMyBkaWZmZXJlbnQgc3BlY2llcy4KYGBgCgpJdCBjYW4gYWxzbyBiZSB1c2VmdWwgdG8gbG9vayBhdCB0aGUgdG9wIGFuZCBib3R0b20gb2YgeW91ciBkYXRhc2V0IHVzaW5nIHRoZSAqKmhlYWQoKSoqIGFuZCAqKnRhaWwoKSoqIGZ1bmN0aW9ucywgd2hpY2ggc2hvdyB0aGUgZmlyc3QgNiByb3dzIGFuZCBsYXN0IDYgcm93cyByZXNwZWN0aXZlbHkuIFRoaXMgaXMgdXNlZnVsIHRvIGVuc3VyZSB0aGF0IHRoZSBkYXRhIG1ha2VzIHNlbnNlICh0aGUgZGF0YSBpcyBudW1lcmljIGlmIHlvdSB3ZXJlIGV4cGVjdGluZyB0aGF0KSBhbmQgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIGNvcnJlY3QgbnVtYmVyIG9mIHJvd3MgYXJlIHByZXNlbnQgKGZvciBleGFtcGxlLCBtYWtlIHN1cmUgdGhhdCB0aGUgbGFzdCBmZXcgcm93cyBhcmUgbm90IGVtcHR5KS4gT3IsIGlmIHRoZSBkYXRhIGlzIHRpbWUgZGVwZW5kZW50LCB5b3UgY2FuIHVzZSB0aGVzZSBmdW5jdGlvbnMgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIGZpcnN0IHRpbWVzIGFyZSBpbiB0aGUgZmlyc3Qgcm93IGFuZCB0aGUgbGFzdCB0aW1lcyBhcmUgYXQgdGhlIGVuZC4KYGBge3IgaGVhZCgpIGFuZCB0YWlsKCl9CiNUaGlzIGNodW5rIHdpbGwgb3V0cHV0IHR3byBmdW5jdGlvbnMsIGFuZCBpdCB3aWxsIHNlcGFyYXRlIHRoZW0gaW50byB0d28gd2luZG93cyBpZiB5b3UgcnVuIHRoZSB3aG9sZSBjaHVuay4gSGVyZSwgdGhlIGxlZnQgd2luZG93IGlzIHRoZSBoZWFkIGZ1bmN0aW9uLCBhbmQgdGhlIHJpZ2h0IHdpbmRvdyBpcyB0aGUgdGFpbCBmdW5jdGlvbi4gVGhlIG91dHB1dCB3aW5kb3dzIHdpbGwgYWx3YXlzIHByb2NlZWQgbGVmdCB0byByaWdodCB0byBjb3JyZXNwb25kIHdpdGggeW91ciBjb2RlIGZyb20gdG9wIHRvIGJvdHRvbS4KaGVhZChJcmlzRGF0YSkKdGFpbChJcmlzRGF0YSkKYGBgCgpBIHZlcnkgdXNlZnVsIGZ1bmN0aW9uIGZvciBkYXRhIGV4cGxvcmF0aW9uIGlzICoqc3VtbWFyeSgpKiouIFRoaXMgb3V0cHV0cyB0aGUgbWVhbiwgbWVkaWFuLCBtaW4sIG1heCwgYW5kIGZpcnN0IGFuZCB0aGlyZCBxdWFydGlsZXMgb2YgYW55IG51bWVyaWMgZGF0YSwgYW5kIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIHdpdGhpbiBvdXIgdmFyaWFibGVzLiBUaGlzIGlzIGFuIGltcG9ydGFudCBzdGVwIGluIGFueSBkYXRhIGV4cGxvcmF0aW9uLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIHZhbGlkYXRpbmcgeW91ciBkYXRhIGFnYWluc3QgZXh0ZXJuYWwgc291cmNlcy4gSWYgZXh0ZXJuYWwgc291cmNlcyBzaG93IHRoYXQgdGhlIGF2ZXJhZ2Ugc2VwYWwgbGVuZ3RoIG9mIGlyaXNlcyBpcyAxMDAgY20gbG9uZywgYnV0IG91ciBzZXBhbCBsZW5ndGhzIHJhbmdlIGZyb20gNC4zIHRvIDcuOSBjbSwgc29tZXRoaW5nIG1pZ2h0IGJlIHdyb25nLiBMdWNraWx5IHRoZSBhdmVyYWdlIGlzIGNsb3NlciB0byA1LTcgY20sIHNvIG91ciBkYXRhIGRvZXMgbWFrZSBzZW5zZS4KCmBgYHtyIHN1bW1hcnkoKX0Kc3VtbWFyeShJcmlzRGF0YSkKYGBgCgojIyBWaXN1YWxpemF0aW9uIHdpdGggR3JhcGhzICAKTm93IHRoYXQgd2UndmUgc3BlbnQgYSBzdWJzdGFudGlhbCBhbW91bnQgb2YgdGltZSBleHBsb3JpbmcgYW5kIG9yZ2FuaXppbmcgb3VyIGRhdGEsIHdlJ3JlIHJlYWR5IHRvIHN0YXJ0IGFuYWx5emluZyBpdCEgVGhlIGZpcnN0IHN0ZXAgaGVyZSBpcyB0byB2aXN1YWxpemUgb3VyIGRhdGEgc2luY2UgdXAgdW50aWwgdGhpcyBwb2ludCwgYWxsIHdlJ3ZlIGJlZW4gbG9va2luZyBhdCBhcmUgbnVtYmVycyAod2hpY2ggY2FuIGJlIGhhcmQgZm9yIGlkZW50aWZ5aW5nIHJlbGF0aW9uc2hpcHMgYW5kIHBhdHRlcm5zIGJldHdlZW4gdmFyaWFibGVzKS4gV2hlbiBjb25zaWRlcmluZyB3aGF0IGdyYXBocyB3b3VsZCBiZSBiZXN0IGZvciB2aXN1YWxpemluZyBvdXIgZGF0YSwgd2Ugc2hvdWxkIGNvbnNpZGVyIG91ciBxdWVzdGlvbnMgb2YgaW50ZXJlc3QgYW5kIHdoYXQgdHlwZXMgb2YgdmFyaWFibGVzIHdlJ3JlIGRlYWxpbmcgd2l0aC4gQXMgYSByZW1pbmRlciwgb3VyIHR3byBxdWVzdGlvbnMgb2YgaW50ZXJlc3QgYXJlIGJlbG93OiAgCgoxLiBBcmUgc2VwYWwgYW5kIHBldGFsIGRpbWVuc2lvbnMgY29ycmVsYXRlZCB3aXRoaW4gYSBzaW5nbGUgc3BlY2llcz8gIAoyLiBEbyBzZXBhbCBhbmQgcGV0YWwgZGltZW5zaW9ucyBkaWZmZXIgYmV0d2VlbiBJcmlzIHNwZWNpZXM/CgojIyMgQXJlIHNlcGFsIGFuZCBwZXRhbCBkaW1lbnNpb25zIGNvcnJlbGF0ZWQgd2l0aGluIGEgc2luZ2xlIHNwZWNpZXM/ICAKTGV0J3MgZm9jdXMgb24gcXVlc3Rpb24gbnVtYmVyIG9uZSBmaXJzdC4gVGhlcmUgYXJlIGEgY291cGxlIGRpZmZlcmVudCwgbW9yZSBzcGVjaWZpYyBxdWVzdGlvbnMgd2UgY2FuIGxvb2sgYXQgd2l0aGluIHRoaXMuIFN1Y2ggYXMsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzZXBhbCBsZW5ndGggYW5kIHNlcGFsIHdpZHRoLCBvciBwZXRhbCBsZW5ndGggYW5kIHBldGFsIHdpZHRoLiBQZXJoYXBzIHdlIGNhbiBldmVuIGNvbXBhcmUgc2VwYWwgbGVuZ3RoIGFuZCBwZXRhbCBsZW5ndGgsIG9yIHNlcGFsIHdpZHRoIGFuZCBwZXRhbCB3aWR0aC4gV293ISBUaGVyZSBhcmUgYSB0b24gb2YgZGlmZmVyZW50IHJlbGF0aW9uc2hpcHMgdG8gbG9vayBhdC4gRm9yIG91ciBwdXJwb3NlcywgbGV0J3MgbmFycm93IGluIG9uIHR3byByZWxhdGlvbnNoaXBzOiAKCjEuIFNlcGFsIGxlbmd0aCBhbmQgc2VwYWwgd2lkdGggIAoyLiBTZXBhbCBsZW5ndGggYW5kIHBldGFsIGxlbmd0aAoKU2luY2UgYWxsIG9mIHRoZXNlIHZhcmlhYmxlcyBhcmUgbnVtZXJpY2FsLCBhIHNjYXR0ZXJwbG90IHdvdWxkIGJlc3QgcmVwcmVzZW50IHRoZSBkYXRhLiBUaGUgKipnZ3Bsb3QqKiBmdW5jdGlvbiBpcyBleHRyZW1lbHkgdXNlZnVsIGZvciBjcmVhdGluZyBncmFwaHMuIEJlbG93IGlzIHRoZSBjb2RlIGZvciBjcmVhdGluZyBhIGJhc2ljIHNjYXR0ZXJwbG90LiAgCmBgYHtyIEJhc2ljIFNjYXR0ZXJwbG90fQojRm9sbG93cyB0aGUgZm9ybTogZ2dwbG90KERhdGFOYW1lLCBhZXMoeD1WYXJpYWJsZU9uZSwgeT1WYXJpYWJsZVR3bykpICsgZ2VvbV9wb2ludCgpCmdncGxvdChJcmlzRGF0YSwgYWVzKHg9c2VwYWwubGVuZ3RoLCB5PXNlcGFsLndpZHRoKSkgKyBnZW9tX3BvaW50KCkKCiNMZWFybmluZyBjaGVjazogVHJ5IHJ1bm5pbmcgdGhlIGNvZGUgd2l0aG91dCArIGdlb21fcG9pbnQoKS4gV2hhdCBoYXBwZW5zPwpgYGAKCkluIHRoZSBvdXRwdXQgd2Ugc2VlIGEgYmFzaWMgc2NhdHRlcnBsb3Qgd2l0aG91dCBhbnkgY2xlYXIgcGF0dGVybi4gVGhpcyBjb3VsZCBiZSBiZWNhdXNlIHdlJ3JlIGxvb2tpbmcgYXQgZGF0YSBmb3IgYWxsIHRocmVlIHNwZWNpZXMuIFJlbWVtYmVyLCBvdXIgb3JpZ2luYWwgcXVlc3Rpb24gd2FzIGFib3V0IHdoZXRoZXIgdGhlcmUgd2VyZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHZhcmlhYmxlcyB3aXRoaW4gYSAqc2luZ2xlKiBzcGVjaWVzLiBXZSBjYW4gZWl0aGVyIGZpbHRlciB0aGUgZGF0YSBzbyB0aGF0IHdlIGNhbiBwbG90IG9uZSBzcGVjaWVzIGF0IGEgdGltZSwgb3Igd2UgY2FuIGp1c3QgY29sb3ItY29kZSB0aGUgcG9pbnRzIG9uIHRoZSBzY2F0dGVycGxvdCBieSBzcGVjaWVzIHNvIHdlIGNhbiBzdGlsbCBsb29rIGF0IGFsbCBvZiB0aGUgZGF0YSAodGhpcyBpcyB0aGUgbWV0aG9kIHdlJ2xsIHVzZSkuICAKYGBge3IgU2hhcGVzIGJ5IFNwZWNpZXN9CmdncGxvdChJcmlzRGF0YSwgYWVzKHg9c2VwYWwubGVuZ3RoLCB5PXNlcGFsLndpZHRoLCBzaGFwZT1zcGVjaWVzKSkgKyBnZW9tX3BvaW50KCkKI0FkZGluZyBzaGFwZT1zcGVjaWVzIGluIHRoZSBjb2RlIGxpbmUgdGVsbHMgUiB0byBncm91cCB0aGUgcG9pbnRzIGFjY29yZGluZyB0byBzcGVjaWVzIGFuZCB0byBkaWZmZXJlbnRpYXRlIHRoZSBzcGVjaWVzIHVzaW5nIGRpZmZlcmVudCBzaGFwZXMuCmBgYAoKQnkgc2VwYXJhdGluZyB0aGUgZGF0YSBwb2ludHMgYWNjb3JkaW5nIHRvIHNwZWNpZXMgd2UgY2FuIHN0YXJ0IHRvIHNlZSBzb21lIHBhdHRlcm5zIGVtZXJnaW5nIGJldHdlZW4gdGhlIHZhcmlhYmxlcyB3aXRoaW4gZWFjaCBzcGVjaWVzLiBIb3dldmVyLCBpdCBzdGlsbCB0YWtlcyBhIHNlY29uZCB0byBkaWZmZXJlbnRpYXRlIGJldHdlZW4gVmVyc2ljb2xvciBhbmQgVmlyZ2luaWNhIHNpbmNlIHRoZXkgb2NjdXB5IHRoZSBzYW1lIGdlbmVyYWwgc3BhY2Ugb24gdGhlIHBsb3QgYW5kIHlvdSBkb24ndCBpbW1lZGlhdGVseSBub3RpY2UgdGhlIGRpZmZlcmVuY2UgaW4gc2hhcGVzLiBUbyBtYWtlIGl0IGVhc2llciB0byBkaXN0aW5ndWlzaCBiZXR3ZWVuIHRoZSB0d28sIHdlIGNhbiB1c2UgY29sb3IgdG8gZGlmZmVyZW50aWF0ZSB0aGUgc3BlY2llcyByYXRoZXIgdGhhbiBzaGFwZS4gIApgYGB7ciBDb2xvci1jb2RpbmcgYnkgU3BlY2llc30KZ2dwbG90KElyaXNEYXRhLCBhZXMoeD1zZXBhbC5sZW5ndGgsIHk9c2VwYWwud2lkdGgsIGNvbG9yPXNwZWNpZXMpKSArIGdlb21fcG9pbnQoKQojQWRkaW5nIGNvbG9yPXNwZWNpZXMgaW4gdGhlIGNvZGUgbGluZSB0ZWxscyBSIHRvIGRpZmZlcmVudGlhdGUgdGhlIHNwZWNpZXMgYnkgY29sb3IgYXMgd2VsbCBhcyBieSBzaGFwZS4KYGBgCgpCYXNlZCBvbiB0aGlzIHNjYXR0ZXJwbG90LCB0aGVyZSBzZWVtcyB0byBiZSBhIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gc2VwYWwgbGVuZ3RoIGFuZCBzZXBhbCB3aWR0aCB3aXRoaW4gZWFjaCBzcGVjaWVzLiBTYXkgeW91IHdhbnRlZCB0byBwcmVzZW50IHRoaXMgZGF0YSBpbiBhIGZvcm1hbCByZXBvcnQuIFlvdSB3b3VsZCBsaWtlbHkgd2FudCB0byBjbGVhbiBpdCB1cCBhIGJpdC4gRm9ydHVuYXRlbHksICoqZ2dwbG90KiogaGFzIGEgKnRvbiogb2Ygd2F5cyB5b3UgY2FuIHNwcnVjZSB1cCB5b3VyIGdyYXBocyB0byBsb29rIG5lYXRlciBhbmQgbW9yZSBwcm9mZXNzaW9uYWwuIExldCdzIHRha2UgYSBsb29rIGF0IHNvbWUgb2YgdGhvc2UgdG9vbHMuICAKYGBge3IgU3BydWNlIGl0IHVwfQpnZ3Bsb3QoSXJpc0RhdGEsIGFlcyh4PXNlcGFsLmxlbmd0aCwgeT1zZXBhbC53aWR0aCwgY29sb3I9c3BlY2llcykpICsKICBnZW9tX3BvaW50KCkKI1RoaXMgY29kZSBydW5zIHRoZSBzYW1lIGFzIHRoZSBjb2RlIHdlIHVzZWQgcHJldmlvdXNseSwgZXZlbiB0aG91Z2ggZ2VvbV9wb2ludCgpIGlzIG9uIGEgc2VwYXJhdGUgbGluZS4gVGhpcyBmZWF0dXJlIGlzIGhlbHBmdWwgZm9yIGJyZWFraW5nIHVwIHlvdXIgY29kZSB3aGVuIHlvdSdyZSBhZGRpbmcgYSBsb3Qgb2YgbW9kaWZpY2F0aW9ucyB0byBhIGdyYXBoLiBXZSdsbCB1c2UgdGhpcyBraW5kIG9mIGZvcm1hdHRpbmcgZm9yIG91ciBncmFwaHMgbW92aW5nIGZvcndhcmQuCgpnZ3Bsb3QoSXJpc0RhdGEsIGFlcyh4PXNlcGFsLmxlbmd0aCwgeT1zZXBhbC53aWR0aCwgY29sb3I9c3BlY2llcykpICsgI0Jhc2ljIHNjYXR0ZXJwbG90IGdyb3VwZWQgYnkgY29sb3IKICBnZW9tX3BvaW50KCkgKyAjQWRkcyBkYXRhIHBvaW50cyB0byBwbG90CiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBzZT1GQUxTRSkgKyAjQWRkcyByZWdyZXNzaW9uIGxpbmVzCiAgbGFicyh4ID0gIlNlcGFsIExlbmd0aCAoY20pIiwgeSA9ICJTZXBhbCBXaWR0aCAoY20pIikgKyAjUmVuYW1lcyBheGlzIGxhYmVscwogIGxhYnMoY29sPSJTcGVjaWVzIikgKyAjUmVuYW1lcyBsZWdlbmQKICBsYWJzKHRpdGxlID0gIlNlcGFsIFdpZHRoIHZzLiBTZXBhbCBMZW5ndGggaW4gVGhyZWUgSXJpcyBTcGVjaWVzIikgKyAjR2l2ZXMgdGhlIHBsb3QgYSB0aXRsZQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAjQ2VudGVycyB0aGUgcGxvdCB0aXRsZQpgYGAKClRoaXMgcGxvdCBsb29rcyBtdWNoIG5pY2VyIGFuZCBpcyBlYXNpZXIgdG8gaW50ZXJwcmV0IGNvbXBhcmVkIHRvIG91ciBpbml0aWFsIHNjYXR0ZXJwbG90LiBOb3cgdGhhdCB3ZSBoYXZlIHRoZSBjb2RlIGFsbCBmaWd1cmVkIG91dCwgd2UgY2FuIGVzc2VudGlhbGx5IGNvcHkgYW5kIHBhc3RlIHRoZSBzYW1lIGNvZGUgYnV0IHN1YnN0aXR1dGUgaW4gbmV3IHZhcmlhYmxlIHRvIGxvb2sgYXQgb3RoZXIgcmVsYXRpb25zaGlwcyBhcyB3ZWxsLiBMZXQncyBsb29rIGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAgCmBgYHtyIFNjYXR0ZXJwbG90IGNvbXBhcmluZyBQZXRhbCBMZW5ndGggYW5kIFNlcGFsIExlbmd0aH0KZ2dwbG90KElyaXNEYXRhLCBhZXMoeD1zZXBhbC5sZW5ndGgsIHk9cGV0YWwubGVuZ3RoLCBjb2xvcj1zcGVjaWVzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBzZT1GQUxTRSkgKwogIGxhYnMoeCA9ICJTZXBhbCBMZW5ndGggKGNtKSIsIHkgPSAiUGV0YWwgTGVuZ3RoIChjbSkiKSArCiAgbGFicyhjb2w9IlNwZWNpZXMiKSArCiAgbGFicyh0aXRsZSA9ICJQZXRhbCBMZW5ndGggdnMuIFNlcGFsIExlbmd0aCBpbiBUaHJlZSBJcmlzIFNwZWNpZXMiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCmBgYApUaGlzIHNjYXR0ZXJwbG90IHJldmVhbHMgdGhhdCB0aGVyZSBhbHNvIHNlZW1zIHRvIGJlIGEgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBzZXBhbCBsZW5ndGggYW5kIHBldGFsIGxlbmd0aCB3aXRoaW4gZWFjaCBzcGVjaWVzLCB0aG91Z2ggdGhlIHN0cmVuZ3RoIG9mIHRoYXQgcmVsYXRpb25zaGlwIG1heSBkaWZmZXIgYmV0d2VlbiBzcGVjaWVzLiBGZWVsIGZyZWUgdG8gdXNlIHRoaXMgc2NhdHRlcnBsb3QgY29kZSB0byB2aXN1YWxpemUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIG90aGVyIHZhcmlhYmxlcyBhcyB3ZWxsLgoKIyMjIERvIHNlcGFsIGFuZCBwZXRhbCBkaW1lbnNpb25zIGRpZmZlciBiZXR3ZWVuIElyaXMgc3BlY2llcz8gIApPdXIgbmV4dCBxdWVzdGlvbiBvZiBpbnRlcmVzdCBkZWFscyB3aXRoIGNvbXBhcmluZyBkaW1lbnNpb25zICpiZXR3ZWVuKiBzcGVjaWVzLiBPbmNlIGFnYWluLCB0aGVyZSBhcmUgYSB0b24gb2YgZGlmZmVyZW50LCBtb3JlIHNwZWNpZmljIHF1ZXN0aW9ucyB3ZSBjYW4gbG9vayBhdCB3aXRoaW4gdGhpcy4gRm9yIG91ciBwdXJwb3NlcywgbGV0J3MgZm9jdXMgb24gc2VwYWwgbGVuZ3RoIGJldHdlZW4gc3BlY2llcy4gU2luY2Ugc3BlY2llcyBpcyBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlLCBhIGJveHBsb3Qgd291bGQgYmVzdCByZXByZXNlbnQgdGhlIGRhdGEuIFRoZSBjb2RlIGZvciBhIGJhc2ljIGJveHBsb3QgaXMgYmVsb3cuICAKYGBge3IgQmFzaWMgYm94cGxvdH0KZ2dwbG90KElyaXNEYXRhLCBhZXMoeD1zcGVjaWVzLCB5PXBldGFsLmxlbmd0aCkpICsgZ2VvbV9ib3hwbG90KCkKI1JlcGxhY2luZyBnZW9tX3BvaW50KCkgZnJvbSBvdXIgYmFzaWMgc2NhdHRlcnBsb3QgY29kZSB3aXRoIGdlb21fYm94cGxvdCgpIHRlbGxzIFIgdG8gbWFrZSBhIGJveHBsb3QuCmBgYAoKVGhlcmUgYXBwZWFycyB0byBiZSBhIGRpZmZlcmVuY2UgaW4gc2VwYWwgbGVuZ3RoIGJldHdlZW4gc3BlY2llcyAobm90ZTogZGV0ZXJtaW5pbmcgd2hldGhlciBvciBub3QgdGhhdCBkaWZmZXJlbmNlIGlzIHNpZ25pZmljYW50IGlzIGZvciBsYXRlciBzdGF0aXN0aWNhbCB0ZXN0aW5nKS4gSnVzdCBhcyB3ZSBkaWQgYmVmb3JlLCBsZXQncyBzcHJ1Y2UgdXAgb3VyIHBsb3QgYSBiaXQuICAKYGBge3IgRmFuY3kgQm94cGxvdH0KZ2dwbG90KElyaXNEYXRhLCBhZXMoeD1zcGVjaWVzLCB5PXBldGFsLmxlbmd0aCwgZmlsbD1zcGVjaWVzKSkgKyAjQWRkaXRpb24gb2YgZmlsbD1zcGVjaWVzIGFkZHMgY29sb3IKICBnZW9tX2JveHBsb3QoKSArICNTcGVjaWZpZXMgYm94cGxvdAogIGxhYnMoeCA9ICJTcGVjaWVzIiwgeSA9ICJQZXRhbCBMZW5ndGggKGNtKSIpICsgI1JlbmFtZXMgYXhlcwogIGxhYnModGl0bGUgPSAiUGV0YWwgTGVuZ3RoIGZvciBUaHJlZSBJcmlzIFNwZWNpZXMiKSArICNHaXZlcyBwbG90IGEgdGl0bGUKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyAjQ2VudGVycyB0aXRsZQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgI1JlbW92ZXMgbGVnZW5kCmBgYAoKT25jZSB5b3UgZ2V0ICpyZWFsbHkqIGdvb2Qgd2l0aCBSLCB5b3UnbGwgYmUgYWJsZSB0byBtYWtlIHBsb3RzIGxpa2UgdGhlIG9uZSBiZWxvdywgd2hlcmUgeW91IGluY2x1ZGUgdGhlIHNpZ25pZmljYW5jZSBiYXJzIGZvciBwYWlyd2lzZSBjb21wYXJpc29ucyBiZXR3ZWVuIGVhY2ggb2YgdGhlIHNwZWNpZXMuIEV2ZW4gdGhvdWdoIHdlJ3JlIGdldHRpbmcgYWhlYWQgb2Ygb3Vyc2VsdmVzIGhlcmUsIGZlZWwgZnJlZSB0byBwbGF5IGFyb3VuZCB3aXRoIHRoZSBjb2RlIGJlbG93IHRvIG1ha2UgcGxvdHMgZm9yIG90aGVyIHZhcmlhYmxlcyBhbmQgbG9vayBhdCB0aGUgcC12YWx1ZXMgZm9yIHBhaXJ3aXNlIGNvbXBhcmlzb25zIGJldHdlZW4gc3BlY2llcy4gIApgYGB7cn0KY29tcGFyZV9tZWFucyhwZXRhbC5sZW5ndGggfiBzcGVjaWVzLCAgZGF0YSA9IElyaXNEYXRhKQpteV9jb21wYXJpc29ucyA8LSBsaXN0KGMoIlNldG9zYSIsICJWZXJzaWNvbG9yIiksIGMoIlNldG9zYSIsICJWaXJnaW5pY2EiKSwgYygiVmVyc2ljb2xvciIsICJWaXJnaW5pY2EiKSkKICAKZ2dwbG90KElyaXNEYXRhLCBhZXMoeD1zcGVjaWVzLCB5PXBldGFsLmxlbmd0aCwgZmlsbD1zcGVjaWVzKSkgKyAjQWRkaXRpb24gb2YgZmlsbD1zcGVjaWVzIGFkZHMgY29sb3IKICBnZW9tX2JveHBsb3QoKSArCiAgbGFicyh4ID0gIlNwZWNpZXMiLCB5ID0gIlBldGFsIExlbmd0aCAoY20pIikgKyAjUmVuYW1lcyBheGVzCiAgbGFicyh0aXRsZSA9ICJQZXRhbCBMZW5ndGggZm9yIFRocmVlIElyaXMgU3BlY2llcyIpICsgI0dpdmVzIHBsb3QgYSB0aXRsZQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArICNDZW50ZXJzIHRpdGxlCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArICNSZW1vdmVzIGxlZ2VuZAogIHN0YXRfY29tcGFyZV9tZWFucyhjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zKQpgYGAKCiMjIEh5cG90aGVzaXMgVGVzdGluZyB3aXRoIFN0YXRpc3RpY2FsIFRlc3RzICAKVXAgdW50aWwgdGhpcyBwb2ludCB3ZSd2ZSBiZWVuIGxvb2tpbmcgYXQgdGhlIGRhdGEgd2l0aCBzb21lIHF1ZXN0aW9ucyBpbiBtaW5kIGFib3V0IHJlbGF0aW9uc2hpcHMgaW4gdGhlIGRhdGEuIEZvciBzdGF0aXN0aWNhbCB0ZXN0cywgd2UgbmVlZCBhIHNwZWNpZmljIHF1ZXN0aW9uIG9yIGh5cG90aGVzaXMgdG8gdGVzdC4gT3VyIGh5cG90aGVzaXMgaXMgdGhhdCBwZXRhbCBsZW5ndGggZGlmZmVycyBzaWduaWZpY2FudGx5IGJldHdlZW4gSXJpcyBzcGVjaWVzLiBXZSB3aWxsIHRlc3QgdGhpcyBoeXBvdGhlc2lzIGJlbG93LgoKIyMjIFJlcXVpcmVtZW50cyBmb3IgVGVzdHMgIApOb3cgd2UgY2FuIG1vdmUgb24gdG8gYW5hbHl6aW5nIG91ciBkYXRhIG1vcmUgY3JpdGljYWxseSB3aXRoIHN0YXRpc3RpY2FsIHRlc3RpbmcgZm9yIHNwZWNpZmljIGh5cG90aGVzZXMuIFdoZW4gdXNpbmcgc3RhdGlzdGljYWwgdGVzdHMsIGFsd2F5cyBiZSBzdXJlIHRvIGNoZWNrIHRoZSBhc3N1bXB0aW9ucyBtYWRlIGJ5IHRoZSBwYXJ0aWN1bGFyIHRlc3QgeW91IHBsYW4gdG8gdXNlLiBUaGlzIGlzIGltcG9ydGFudCBiZWNhdXNlIG1hbnkgY29tbW9uIHN0YXRpc3RpY2FsIHRlc3RzLCBpbmNsdWRpbmcgdGhlIHR3by1zYW1wbGUgdC10ZXN0IHdlIHdpbGwgdXNlIGhlcmUsIGFzc3VtZSB0aGF0IHRoZSBkYXRhc2V0cyBiZWluZyBjb21wYXJlZCBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFdoaWxlIG11Y2ggYmlvbG9naWNhbCBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB0aGlzIGlzIG5vdCBhbHdheXMgdHJ1ZSwgc28gYmUgc3VyZSB0byBleHBsb3JlIGFuZCB1bmRlcnN0YW5kIHRoZSBiZWhhdmlvciBvZiB5b3VyIGRhdGEgYmVmb3JlIHBlcmZvcm1pbmcgdGVzdHMuCgpUaGUgKipzaGFwaXJvLnRlc3QqKiBmdW5jdGlvbiBhbGxvd3MgdXMgdG8gY2hlY2sgaWYgb3VyIGRhdGEgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIElmIHRoZSBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB0aGUgcC12YWx1ZSByZXR1cm5lZCBieSB0aGUgc2hhcGlybyB0ZXN0IHNob3VsZCBiZSBncmVhdGVyIHRoYW4gMC4wNS4gSWYgdGhlcmUgYXJlIG11bHRpcGxlIGdyb3Vwcy9wb3B1bGF0aW9ucyB3aXRoaW4gYSBkYXRhIHNldCAoZm9yIGV4YW1wbGUsIG11bHRpcGxlIHNwZWNpZXMgb2YgaXJpcyksIGl0J3MgaW1wb3J0YW50IHRvIHRlc3QgZm9yIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aXRoaW4gZWFjaCBvZiB0aG9zZSBwb3B1bGF0aW9ucyBzZXBhcmF0ZWx5LiBMb29raW5nIGF0IHRoZSBkaXN0cmlidXRpb24gYXMgYSB3aG9sZSBtYXkgbGVhZCB1cyB0byB0aGluayB0aGUgZGF0YSBpcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgd2hlbiBpdCBhY3R1YWxseSBpcyB3aXRoaW4gZWFjaCBwb3B1bGF0aW9uLiBUaGlzIGlzIGFjdHVhbGx5IHRoZSBjYXNlIGZvciB1cywgYXMgeW91IGNhbiBzZWUgd2l0aCB0aGUgb3V0cHV0IGJlbG93LgpgYGB7ciBTaGFwaXJvIFRlc3R9CnNoYXBpcm8udGVzdChJcmlzRGF0YSRwZXRhbC5sZW5ndGgpICNOb3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgYXMgYSB3aG9sZSAocCA9IDcuNDEyZS0xMCA8IDAuMDUpCnNoYXBpcm8udGVzdChJcmlzRGF0YSRwZXRhbC5sZW5ndGhbSXJpc0RhdGEkc3BlY2llcz09IlNldG9zYSJdKSAjTm9ybWFsbHkgZGlzdHJpYnV0ZWQgKHAgPSAwLjA1NDgxID4gMC4wNSkKc2hhcGlyby50ZXN0KElyaXNEYXRhJHBldGFsLmxlbmd0aFtJcmlzRGF0YSRzcGVjaWVzPT0iVmVyc2ljb2xvciJdKSAjTm9ybWFsbHkgZGlzdHJpYnV0ZWQgKHAgPSAwLjE1ODUgPiAwLjA1KQpzaGFwaXJvLnRlc3QoSXJpc0RhdGEkcGV0YWwubGVuZ3RoW0lyaXNEYXRhJHNwZWNpZXM9PSJWaXJnaW5pY2EiXSkgI05vcm1hbGx5IGRpc3RyaWJ1dGVkIChwID0gMC4xMDk4ID4gMC4wNSkKYGBgCgpJZiB0aGUgZGF0YSB5b3UgYXJlIHVzaW5nIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZCwgdGVzdCB0byBzZWUgaWYgYSBsb2dhcml0aG1pYyB0cmFuc2Zvcm1hdGlvbiB3b3VsZCBtYWtlIHRoZSBkaXN0cmlidXRpb24gbm9ybWFsLiBJZiBzbywgeW91IHNob3VsZCB1c2UgdGhlIGxvZy10cmFuc2Zvcm1lZCBkYXRhLiBJZiBub3QsIGNvbnRpbnVlIG9uIHdpdGggdGhlIG9yaWdpbmFsLCBub24tdHJhbnNmb3JtZWQgZGF0YSBidXQgbm90ZSBpbiB5b3VyIHJlcG9ydCB0aGF0IGFueSBzdGF0aXN0aWNhbCB0ZXN0IHJlc3VsdHMgc2hvdWxkIGJlIGludGVycHJldGVkIHdpdGggY2F1dGlvbiwgZ2l2ZW4gdGhhdCB0aGUgYmFzZSByZXF1aXJlbWVudHMgZm9yIGFjY3VyYXRlIHVzZSBvZiB0aGUgdGVzdCBoYXZlIG5vdCBiZWVuIG1ldC4gCgpTaW5jZSB0aGUgZGF0YSBmb3IgcGV0YWwgbGVuZ3RoIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIHdpdGhpbiBlYWNoIHNwZWNpZXMsIGEgbG9nIHRyYW5zZm9ybWF0aW9uIGlzIG5vdCBuZWNlc3NhcnkgaW4gb3VyIGNhc2UuIFdlIHdpbGwgcHJvY2VlZCB3aXRoIHRoZSBub24tdHJhbnNmb3JtZWQgZGF0YS4gSG93ZXZlciwgaGVyZSBpcyBhbiBleGFtcGxlIG9mIGhvdyB5b3Ugd291bGQgcGVyZm9ybSBhIGxvZyB0cmFuc2Zvcm1hdGlvbiBpZiB5b3UgbmVlZGVkIHRvOgpgYGB7ciBMb2cgVHJhbnNmb3JtYXRpb259CiNsb2cgdHJhbnNmb3JtIHRoZSBkYXRhIGFuZCBhc3NpZ24gaXQgdG8gYSB2YXJpYWJsZQpsb2cucGV0YWwubGVuZ3RoIDwtIGxvZyhJcmlzLkRhdGEkcGV0YWwubGVuZ3RoKQojdGVzdCBmb3Igbm9ybWFsaXR5IG9mIHRoaXMgbmV3bHkgdHJhbnNmb3JtZWQgZGF0YQpzaGFwaXJvLnRlc3QoSXJpc0RhdGEkbG9nLnBldGFsLmxlbmd0aCkKYGBgCgpOb3RlIHRoYXQgZWFjaCBzdGF0aXN0aWNhbCB0ZXN0IHdoaWNoIGFzc3VtZXMgbm9ybWFsaXR5IGFsc28gaGFzIGEgc2FtcGxlIHNpemUgcmVxdWlyZW1lbnQgd2hpY2ggY2FuIGFsbG93IGZvciB0aGVtIHRvIHByb2R1Y2UgYWNjdXJhdGUgcmVzdWx0cyB1c2luZyBub24tbm9ybWFsIGRhdGEuIEZvciBhIHR3by1zYW1wbGUgdC10ZXN0IG9yIGEgb25lLXdheSBBTk9WQSB0ZXN0LCBlYWNoIGdyb3VwIGlzIHJlcXVpcmVkIHRvIGhhdmUgYSBzYW1wbGUgc2l6ZSBvZiBhdCBsZWFzdCAxNSBvYnNlcnZhdGlvbnMgdG8gb3ZlcmNvbWUgdGhlIG5lZWQgZm9yIG5vcm1hbGl0eS4gSWYgeW91ciBzYW1wbGVzIGRvIGZpdCB0aGlzIHJlcXVpcmVtZW50LCB5b3UgY2FuIHByb2NlZWQgd2l0aG91dCB3b3JyeWluZyBhYm91dCBub3JtYWxpdHkuIFRoaXMgY3V0b2ZmIGlzIGRpZmZlcmVudCBmb3IgZWFjaCB0eXBlIG9mIHRlc3QsIHNvIGFsd2F5cyBiZSBzdXJlIHRvIGNoZWNrIGJlZm9yZSB5b3UgZGlzcmVnYXJkIGFueSByZXF1aXJlbWVudHMuCgojIyMjIEFOT1ZBIGFuZCBUd28tc2FtcGxlIFQtdGVzdHMgIApJbiBvcmRlciB0byBhbmFseXplIHdoZXRoZXIgcGV0YWwgbGVuZ3RoIGRpZmZlcnMgc2lnbmlmaWNhbnRseSBiZXR3ZWVuIHNwZWNpZXMsIHdlIGNhbiBwZXJmb3JtIGFuIEFOT1ZBLiBXZSBkbyB0aGlzIHdpdGggdGhlICoqYW92KCkqKiBmdW5jdGlvbi4gSXQncyBiZXN0IHRvIGFzc2lnbiB0aGUgZnVuY3Rpb24gdG8gYSB2YXJpYWJsZSB0aGF0IHlvdSBjYW4gdGhlbiBydW4gYSBzdW1tYXJ5IG9mIHRvIHNlZSB0aGUgb3V0cHV0IGZyb20gdGhlIEFOT1ZBIHRlc3QuCmBgYHtyIEFOT1ZBfQphbm92YSA8LSBhb3YocGV0YWwubGVuZ3RoIH4gc3BlY2llcywgZGF0YSA9IElyaXNEYXRhKQpzdW1tYXJ5KGFub3ZhKQpgYGAKClRoZSBBTk9WQSB0ZXN0IHJldHVybmVkIGEgcC12YWx1ZSA8IDJlLTE2IHdoaWNoIGlzIG11Y2ggbGVzcyB0aGFuIDAuMDUgKHRoZSBzdGFuZGFyZCBzaWduaWZpY2FuY2UgbGV2ZWwpLiBJZiB5b3UgcmVjYWxsIGZyb20gc3RhdGlzdGljcywgdGhpcyBnaXZlcyB1cyBldmlkZW5jZSB0aGF0IHBldGFsIGxlbmd0aCBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmb3IgYXQgbGVhc3Qgb25lIG9mIHRoZSBncm91cHMgKHNwZWNpZXMpLCBidXQgd2UgZG9uJ3Qga25vdyB3aGljaC4gSW4gb3JkZXIgdG8gZnVydGhlciBhbmFseXplIHBldGFsIGxlbmd0aCBiZXR3ZWVuIHNwZWNpZXMsIHdlIGNhbiBjb25kdWN0IHBhaXJ3aXNlIHQtdGVzdHMgdG8gc2VlIHdoaWNoIHNwZWNpZXMnIHBldGFsIGxlbmd0aHMgc2lnbmlmaWNhbnRseSBkaWZmZXIgZnJvbSBvbmUgYW5vdGhlci4gSW4gb3JkZXIgdG8gY29uZHVjdCBwYWlyd2lzZSBjb21wYXJpc29ucywgd2UgbmVlZCB0byBmaWx0ZXIgdGhlIGRhdGEgaW50byB0aHJlZSBkYXRhIHN1YnNldHMsIG9uZSBmb3IgZWFjaCBwYWlyd2lzZSBjb21wYXJpc29uLiBXZSBjYW4gZG8gdGhpcyB1c2luZyB0aGUgKipmaWx0ZXIoKSoqIGZ1bmN0aW9uIGFuZCBhc3NpZ24gZWFjaCBmaWx0ZXJlZCBkYXRhc2V0IHRvIGEgbmV3IGRhdGFzZXQuCmBgYHtyIGZpbHRlcigpIGFuZCBQYWlyd2lzZSB0LXRlc3RzfQojZmlsdGVyKCkgdXNlcyB0aGUgZm9ybTogZmlsdGVyKERhdGFOYW1lLCBWYXJpYWJsZU5hbWU9VmFsdWUpLiBUaGlzIGluZGljYXRlcyB0aGF0IHdlIHdhbnQgdG8gcHVsbCBhbGwgb2JzZXJ2YXRpb25zIHdpdGggdGhlIHZhbHVlIHdlIGluZGljYXRlLiBXZSBjYW4gYWxzbyB1c2UgIT0gaW5zdGVhZCBvZiA9IGluIHRoZSBmdW5jdGlvbiB0byBpbmRpY2F0ZSAiZG9lcyBub3QgZXF1YWwgdG8uIiBUaGlzIGluZGljYXRlcyB0aGF0IHdlIHdhbnQgdG8gaW5jbHVkZSBhbGwgb2JzZXJ2YXRpb25zIGV4Y2VwdCB0aG9zZSB3aXRoIHRoZSB2YWx1ZSB3ZSBpbmRpY2F0ZS4KU2V0b3NhVmVyc2ljb2xvciA8LSBmaWx0ZXIoSXJpc0RhdGEsIHNwZWNpZXMhPSJWaXJnaW5pY2EiKQpTZXRvc2FWaXJnaW5pY2EgPC0gZmlsdGVyKElyaXNEYXRhLCBzcGVjaWVzIT0iVmVyc2ljb2xvciIpClZlcnNpY29sb3JWaXJnaW5pY2EgPC0gZmlsdGVyKElyaXNEYXRhLCBzcGVjaWVzIT0iU2V0b3NhIikKCnQudGVzdChwZXRhbC5sZW5ndGggfiBzcGVjaWVzLCBkYXRhID0gU2V0b3NhVmVyc2ljb2xvcikgI1NpZ25pZmljYW50IChwIDwgMi4yZS0xNikKdC50ZXN0KHBldGFsLmxlbmd0aCB+IHNwZWNpZXMsIGRhdGEgPSBTZXRvc2FWaXJnaW5pY2EpICNTaWduaWZpY2FudCAocCA8Mi4yZS0xNikKdC50ZXN0KHBldGFsLmxlbmd0aCB+IHNwZWNpZXMsIGRhdGEgPSBWZXJzaWNvbG9yVmlyZ2luaWNhKSAjU2lnbmlmaWNhbnQgKHAgPCAyLjJlLTE2KQpgYGAKClRoZSByZXN1bHRzIGZyb20gdGhlIHBhaXJ3aXNlIGNvbXBhcmlzb25zIGluZGljYXRlIHRoYXQgdGhlIG1lYW4gcGV0YWwgbGVuZ3RoIGZvciB0aGUgdGhyZWUgc3BlY2llcyBhcmUgZWFjaCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIG9uZSBhbm90aGVyLiBXZSBhY3R1YWxseSBzZWUgdGhlIHNhbWUgcC12YWx1ZXMgcmV0dXJuZWQgYnkgdGhlIHBhaXJ3aXNlIHQtdGVzdHMgZGlzcGxheWVkIG9uIHRoZSBib3gtcGxvdCB3aXRoIHAtdmFsdWVzLiBUaGlzIG1ha2VzIHNlbnNlLCBzaW5jZSB0aGUgcC12YWx1ZXMgb24gdGhlIGJveHBsb3QgcmVzdWx0ZWQgZnJvbSBwYWlyd2lzZSBjb21wYXJpc29ucy4gT3ZlcmFsbCwgd2UgaGF2ZSBldmlkZW5jZSB0byBzdXBwb3J0IHRoZSBoeXBvdGhlc2lzIHRoYXQgcGV0YWwgbGVuZ3RoIGRpZmZlcnMgc2lnbmlmaWNhbnRseSBiZXR3ZWVuIElyaXMgc3BlY2llcy4KCiMjIyBMaW5lYXIgTW9kZWwgICAKV2UgY2FuIGFsc28gdXNlIGEgbGluZWFyIG1vZGVsIGFzIGEgc3RhdGlzdGljYWwgdGVzdCB0byBsb29rIGF0IHJlbGF0aW9uc2hpcHMgaW4gdGhlIGRhdGEuIFdlIGFscmVhZHkgdXNlZCBhIGxpbmVhciBtb2RlbCB0byBzb21lIGRlZ3JlZSB3aGVuIHdlIGNyZWF0ZWQgb3VyIHNjYXR0ZXJwbG90IGFuZCBpbmNsdWRlZCBhIHJlZ3Jlc3Npb24gbGluZS4gSG93ZXZlciwgbm93IHdlJ3JlIGdvaW5nIHRvIGxvb2sgYXQgYSBsaW5lYXIgbW9kZWwgbW9yZSBxdWFudGl0YXRpdmVseSByYXRoZXIgdGhhbiBxdWFsaXRhdGl2ZWx5LiBUaGUgKipsbSgpKiogZnVuY3Rpb24gYWxsb3dzIHVzIHRvIGJ1aWxkIGEgbGluZWFyIG1vZGVsIHdpdGggb3VyIGRhdGEuICAKYGBge3IgTGluZWFyIE1vZGVsfQojVGhlIGxtKCkgZnVuY3Rpb24gdGFrZXMgdGhlIGZvcm06IGxtKERlcGVuZGVudFZhcmlhYmxlIH4gSW5kZXBlbmRlbnRWYXJpYWJsZSwgZGF0YT1EYXRhTmFtZSkKbG1TcGVjaWVzIDwtIGxtKHBldGFsLmxlbmd0aCB+IHNwZWNpZXMsIGRhdGE9SXJpc0RhdGEpCnN1bW1hcnkobG1TcGVjaWVzKQpgYGAKClRoZSBwLXZhbHVlIHJldHVybmVkIHdpdGggdGhlIGxpbmVhciBtb2RlbCBpcyA8IDIuMmUtMTYuIFRoaXMgc2hvd3MgdXMgdGhhdCBwZXRhbCBsZW5ndGggaXMgZGVwZW5kZW50IG9uL2V4cGxhaW5lZCBieSBzcGVjaWVzLiBUaGlzIGlzIHdoYXQgd2UgZXhwZWN0ZWQgYmFzZWQgb24gZWFybGllciBzdGF0aXN0aWNhbCB0ZXN0cy4gRm9yIHRoZSBzYWtlIG9mIHRoaXMgdHV0b3JpYWwsIGxldCdzIGV4cGxvcmUgYW5vdGhlciBsaW5lYXIgbW9kZWwgdGhhdCBsb29rcyBhdCBwZXRhbCBsZW5ndGggc2VwYWwgd2lkdGguICAKYGBge3J9CmxtU2VwYWxXaWR0aCA8LSBsbShwZXRhbC5sZW5ndGggfiBzZXBhbC53aWR0aCwgZGF0YT1JcmlzRGF0YSkKc3VtbWFyeShsbVNlcGFsV2lkdGgpCmBgYAoKVGhpcyBsaW5lYXIgbW9kZWwgcmV0dXJuZWQgYSBwLXZhbHVlIG9mIDQuNTEzZS04LiBXaGlsZSB0aGlzIGlzIHN0aWxsIGEgdmVyeSBzaWduaWZpY2FudCBwLXZhbHVlLCB3ZSBzZWUgdGhhdCBvdXIgbW9kZWwgd2hpY2ggdXNlZCBzcGVjaWVzIHJhdGhlciB0aGFuIHNlcGFsIHdpZHRoIHdhcyBhIGJldHRlciBtb2RlbC4gV2UgY2FuIHJlcHJlc2VudCB0aGUgZGlmZmVyZW5jZSBpbiBob3cgd2VsbCB0aGVzZSB0d28gbW9kZXMgZml0IHRoZSBkYXRhIHdpdGggYW4gQU5PVkEgdGhhdCBjb21wYXJlcyB0aGUgdHdvIG1vZGVscy4KYGBge3IgbGluZWFyIG1vZGVsIGNvbXBhcmlzb259CmFub3ZhKGxtU2VwYWxXaWR0aCwgbG1TcGVjaWVzLCB0ZXN0PSdGJykKYGBgCgpUaGUgQU5PVkEgcmV0dXJuZWQgYSBwLXZhbHVlIDwgMi4yZS0xNi4gVGhpcyBpcyBpbnRlcnByZXRlZCBhcyBoYXZpbmcgc3VmZmljaWVudCBldmlkZW5jZSB0aGF0IHRoZSBzZWNvbmQgbW9kZWwgaW4gdGhlIGNvZGUgbGluZSAoc3BlY2llcyBtb2RlbCkgaXMgYSBiZXR0ZXIgZml0IGZvciB0aGUgZGF0YSB0aGFuIHRoZSBmaXJzdCBtb2RlbCBpbiB0aGUgY29kZSBsaW5lIChzZXBhbCB3aWR0aCBtb2RlbCkuIFNvIHdoaWxlIGJvdGggbW9kZWxzIG1heSBiZSBhIGdvb2QgZml0IGZvciB0aGUgZGF0YSwgdGhlIG1vZGVsIHdpdGggc3BlY2llcyBpcyBhIGJldHRlciBmaXQgb3ZlcmFsbC4gV2UgY2FuIGFsc28gY29uc2lkZXIgd2hldGhlciBhIGxpbmVhciBtb2RlbCB0aGF0IGNvbWJpbmVzICpib3RoKiB2YXJpYWJsZXMgd291bGQgYmUgYW4gZXZlbiBiZXR0ZXIgZml0IHRoYW4gYSBtb2RlbCB0aGF0IG9ubHkgY29uc2lkZXJzIHNwZWNpZXMuCmBgYHtyIENvbWJpbmVkIGxpbmVhciBtb2RlbCBhbmQgY29tcGFyaXNvbn0KbG1TcGVjaWVzU2VwYWxXaWR0aCA8LSBsbShwZXRhbC5sZW5ndGggfiBzcGVjaWVzICsgc2VwYWwud2lkdGgsIGRhdGE9SXJpc0RhdGEpCnN1bW1hcnkobG1TcGVjaWVzU2VwYWxXaWR0aCkKCmFub3ZhKGxtU3BlY2llcywgbG1TcGVjaWVzU2VwYWxXaWR0aCwgdGVzdD0nRicpCmBgYAoKVGhlIEFOT1ZBIHJldHVybmVkIGEgcC12YWx1ZSBvZiAyLjE4NmUtNi4gVGhpcyBpcyBpbnRlcnByZXRlZCBhcyBoYXZpbmcgc3VmZmljaWVudCBldmlkZW5jZSB0aGF0IHRoZSBjb21iaW5lZCBtb2RlbCBpcyBhIGJldHRlciBmaXQgdGhhbiB0aGUgbW9kZWwgdGhhdCBvbmx5IGNvbnNpZGVycyBzcGVjaWVzLiBUaGlzIG1ha2VzIHNlbnNlIHNpbmNlIG91ciBlYXJsaWVyIGFuYWx5c2VzIHJldmVhbGVkIHRoYXQgYWxsIG9mIHRoZSB2YXJpYWJsZXMgaW4gdGhpcyBkYXRhc2V0IHNlZW1lZCB0byBiZSBjbG9zZWx5IHJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlci4KCkNvbmdyYXR1bGF0aW9ucyEgWW91IGp1c3QgZ290IHRocm91Z2ggdGhlICoqUiBmb3IgRHVtbWllcyAoQklPTDIwOCBFZGl0aW9uKSoqIHR1dG9yaWFsLCBhbmQgdGhhdCdzIG5vIGVhc3kgdGFzay4gVGhlIHdvcmxkIG9mIGNvZGluZyBpbiBSIHN0aWxsIGhhcyBzbyBtdWNoIGZvciB5b3UgdG8gZGlzY292ZXIsIGJ1dCB5b3UgaGF2ZSB0aGUgc2tpbGxzIG5vdyB0byBnZXQgc3RhcnRlZCB3aXRoIGl0LiBJZiB0aGlzIHR1dG9yaWFsIGhhcyBsZWZ0IHlvdSBjcmF2aW5nIGZvciBtb3JlIGRhdGEgYW5hbHlzaXMgYW5kIFIga25vd2xlZGdlLCBjaGVjayBvdXQgdGhlIGFkZGl0aW9uYWwgdG9vbHMgYmVsb3cuIEhhcHB5IGNvZGluZyEKCiMjIEFkZGl0aW9uYWwgVG9vbHMgIAojIyMgRXhwbGFuYXRpb24gb2YgcC12YWx1ZXMgIApBIHAtdmFsdWUgcmVwcmVzZW50cyB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUgZ2l2ZW4gdGhlIG91dGNvbWUgb2JzZXJ2ZWQuIEZvciBtb3N0IHB1cnBvc2VzLCBhIHAtdmFsdWUgb2YgMC4wNSBvciBsb3dlciBpcyBjb25zaWRlcmVkIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIEhvd2V2ZXIsIHN0YXVuY2hseSByZWx5aW5nIG9uIHRoaXMgdmFsdWUgY29tZXMgd2l0aCBzb21lIGNvbmNlcm5zIGJlY2F1c2UsIGFsdGhvdWdoIGl0IGlzIGNvbW1vbmx5IHVzZWQgYW5kIGFjY2VwdGVkLCBpdCBpcyBlc3NlbnRpYWxseSBhbiBhcmJpdHJhcnkgY3V0b2ZmLiBUaHVzLCBiZSBzdXJlIHRvIHVuZGVyc3RhbmQgd2hhdCB0aGlzIGN1dG9mZiBtZWFucyBzbyB5b3UgY2FuIGFjY3VyYXRlbHkgZXhwcmVzcyB0aGUgc3RyZW5ndGggb2YgZWFjaCByZXN1bHQuCgpUaGVyZSBhcmUgdHdvIG1haW4gd2F5cyBpbiB3aGljaCB5b3UgY2FuIHVud2l0dGluZ2x5IGFidXNlIHAtdmFsdWVzLiBUaGUgZmlyc3QgaXMga25vd24gYXMgcC1oYWNraW5nIGFuZCBvY2N1cnMgd2hlbiByZXNlYXJjaGVycyBlbmQgdXAgd2l0aCByZXN1bHRzIHdoaWNoIGFyZSBub3Qgc3RhdGlzaXRpY2FsbHkgc2lnbmlmaWNhbnQgYnV0IHRoZW4gY29udGludWUgdG8gZmluZCBuZXcgd2F5cyB0byBtYW5pcHVsYXRlIHRoZSBkYXRhIHVudGlsIHRoZXkgZXZlbnR1YWxseSBmaW5kIHNvbWV0aGluZyBzaWduaWZpY2FudC4gVGhlIHNlY29uZCBpcyB0aHJvdWdoIHdoYXQgU3R1YXJ0IFJpdGNoaWUgY2FsbHMgIkhBUktpbmciIG9yICJIeXBvdGhlc2lzaW5nIEFmdGVyIHRoZSBSZXN1bHRzIGFyZSBLbm93biwiIGluIHdoaWNoIHJlc2VhcmNoZXJzIGNvbWUgdXAgd2l0aCBuZXcgaHlwb3RoZXNlcyBhZnRlciB0aGV5IGZpbmQgdGhhdCB0aGVpciBvcmlnaW5hbCBoeXBvdGhlc2lzIHdhcyBpbnNpZ25pZmljYW50LiBUaGlzIGlzIHByb2JsZW1hdGljIGJlY2F1c2UgaXQgaXMgaW50ZWxsZWN0dWFsbHkgZGlzaG9uZXN0IGFuZCBoaWRlcyBpbnNpZ25pZmljYW50IHJlc3VsdHMgaW4gdGhlIGludGVyZXN0IG9mIG9ubHkgcmVwb3J0aW5nIHRob3NlIHdoaWNoIGFyZSBzaWduaWZpY2FudCAob2Z0ZW4gY2FsbGVkIHRoZSBGaWxlIERyYXdlciBFZmZlY3QpLiBSZW1lbWJlciwgYSBwLXZhbHVlIG9mIDAuMDUgbWVhbnMgdGhhdCB0aGVyZSBpcyBhIDUlIGNoYW5jZSBvZiB0aGUgb2JzZXJ2YXRpb25zIGJlaW5nIGFzIHRoZXkgYXJlIGlmIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgdHJ1ZS4gVGh1cywgaWYgeW91IHRlc3QgMjAgdmFyaWFibGVzLCBpdCBpcyBzdGF0aXN0aWNhbGx5IGxpa2VseSB0aGF0IGF0IGxlYXN0IG9uZSBvZiB0aGVtIHdpbGwgc2hvdyBzaWduaWZpY2FuY2Ugc2ltcGx5IGJ5IGNoYW5jZS4KCiMjIyBSIE1hcmtkb3duIEZvcm1hdHRpbmcgVHJpY2tzICgmIEtuaXR0aW5nKSAgClIgbWFya2Rvd24gaGFzIGEgdG9uIG9mIHVzZWZ1bCBzeW50YXggdHJpY2tzIGZvciBmb3JtYXR0aW5nIHRleHQgaW4gdGhlIGtuaXR0ZWQgdmVyc2lvbiBvZiB5b3VyIGRvY3VtZW50LiBUaGVzZSBpbmNsdWRlOiAgCippdGFsaWNzKiAgCioqYm9sZCoqICAKc3VwZXJzY3JpcHReMTBeICAKfn5zdHJpa2V0aHJvdWdofn4gCgojIExhcmdlIEhlYWRlciAgCiMjIE1lZGl1bS1MYXJnZXIgSGVhZGVyICAKIyMjIE1lZGl1bSBIZWFkZXIgIAojIyMjIFNtYWxsLU1lZGl1bSBIZWFkZXIgIAojIyMjIyBTbWFsbCBoZWFkZXIgIAoKLSBCdWxsZXRlZCBsaXN0ICAKICArIFN1Yi1pdGVtIGluIGxpc3QgIAogIAoxLiBGaXJzdCBsaXN0IGl0ZW0gIAoyLiBTZWNvbmQgbGlzdCBpdGVtICAKMy4gVGhpcmQgbGlzdCBpdGVtCgpUbyB0ZXN0IG91dCBzb21lIG9mIHRoZXNlIHRyaWNrcyB5b3Vyc2VsZiwgeW91J2xsIGhhdmUgdG8ga25pdCB5b3VyIGRvY3VtZW50IHRvIHNlZSB3aGF0IGl0IGxvb2tzIGxpa2Ugb3V0c2lkZSBvZiBSIHN0dWRpby4gTXkgZmF2b3JpdGUgZmlsZSB0eXBlIHRvIGtuaXQgdG8gaXMgYSBwZGYsIGJlY2F1c2UgdGhlc2UgYXJlIGVhc3kgdG8gcmVhZCwgc2F2ZSwgYW5kIHNlbmQuIFlvdSBjYW4gc2V0IHRoZSBmaWxlIHR5cGUgYXQgdGhlIHRvcCBvZiB5b3VyIGRvY3VtZW50IGFuZCB0aGVuIGhpdCB0aGUga25pdCBidXR0b24gKHJlZmVyIHRvIGZpZ3VyZSAzKS4gSXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IGluIG9yZGVyIHRvIGtuaXQsIHlvdSBjYW4ndCBoYXZlIGFueSBlcnJvcnMgaW4geW91ciBjb2RlLiBJZiB5b3UgaGF2ZSBhbnkgbm9uLWZ1bmN0aW9uYWwgY29kZSwgdGhlIGZpbGUgd29uJ3QgYmUgYWJsZSB0byBrbml0LiBZb3UgYWxzbyBuZWVkIHRvIGVuc3VyZSB0aGF0IGFsbCB5b3VyIGNvZGUgY2h1bmtzIGFyZSBuYW1lZCB3aXRoIGEgdW5pcXVlIG5hbWUgaW4gb3JkZXIgdG8ga25pdC4gSWYgeW91IHRyeSBrbml0dGluZyBhbmQgaXQgZG9lc24ndCB3b3JrLCBjaGVjayB0aGF0IHlvdSd2ZSBtZXQgYm90aCBvZiB0aG9zZSByZXF1aXJlbWVudHMgYW5kIHRyeSBhZ2Fpbi4KCiFbS25pdHRpbmddKC4uL1R1dG9yaWFsX1Byb2plY3RfOC9JbWFnZXMvS25pdHRpbmcucG5nKQoKIyBBY2tub3dsZWRnZW1lbnRzICAKMS4gUml0Y2hpZSwgU3R1YXJ0LiAqU2NpZW5jZSBGaWN0aW9ucyogKDIwMjApIHBwLiA5OOKAkzk5CgojIyBHcm91cCBNZW1iZXIgQ29udHJpYnV0aW9ucyAgCjEuIElhbjogTG9hZGluZyBMaWJyYXJpZXMgYW5kIERhdGEsIFVzaW5nIFIsIEV4cGxvcmluZyBZb3VyIERhdGEgIAoyLiBLYWl0bGluOiBUdXRvcmlhbCBzY3JlZW5zaG90cywgQWRkaXRpb25zIHRvIFVzaW5nIFIsIFZpc3VhbGl6YXRpb24gd2l0aCBHcmFwaHMsIHNoYXBpcm8gdGVzdHMsIEFOT1ZBLCB0LXRlc3RzLCBMaW5lYXIgTW9kZWxzLCBNYXJrZG93biBGb3JtYXR0aW5nLCBHaXRIdWIgIAozLiBFbWlseTogTG9nIFRyYW5zZm9ybWF0aW9uLCBwLXZhbHVlIERpc2N1c3Npb24=